対象者
- FlutterでのMaterial 3が気になる人
- Material 3 で導入されたFilledButtonが気になる人
はじめに
FlutterにMaterial 3 が導入されて、ボタンが丸くなり、お洒落になりました(多分、センスないんで、断言できない)。また原色を指定しても、いい感じになっています(ような気がする)。実際どうなのかと思い比較してみます。
また、Material 3になって導入されたFilledButtonがどんな感じかいていきたいと思います。
外観
Material 3 の設定と色の設定が異なるだけの、同じソースの結果を表示してます。
並べてみるとやっぱり、色がちょっと違いますね。
ボタンも丸くなっているだけかと思いましたが、テキストの色が変わってます。
ElevatedButtonのボタンの色が弱くなってますね。元々のスタイルはFilledButtonに取って代わられた感じがします。特にダーク時にボタンの色が黒っぽくて、ぱっと見ボタンと気づかないかも。
Material3ではない | Material 3 (ライト) | Material 3 (ダーク) | |
---|---|---|---|
全体 | |||
差分 | useMaterial3: false, primarySwatch: Colors.red, |
useMaterial3: true, colorSchemeSeed: Colors.red, |
useMaterial3: true, colorSchemeSeed: Colors.red, |
FilledButton
さて、今回は新たに導入されたFilledButtonを見ていきましょう。(onPressは省略してます)
ElevatedButtonと同じようにボタンに色を塗りますが、浮き上がり(影)がない点が異なります。
FilledButton(child: Text('FilledButton')),
FilledButton.tonal(
child: Text('FilledButton.tonal'),
),
FilledButton.icon(
icon: Icon(Icons.add),
label: Text('FilledButton.icon'),
),
FilledButton.tonalIcon(
icon: Icon(Icons.add),
label: Text('FilledButton.tonalIcon'),
),
ボタンの種類としては「デフォルト」「tonal」の2種類 X アイコンの有り無し2種類、で4種類になります。
アイコンの有り無しは、ラベルの左側にアイコンを表示できるか、できないか、だけです。
そして、「デフォルト」「tonal」ではそれぞれ色が異なります。デフォルトがプライマリの色で、tonalがセカンダリの色です。プライマリはCTA(Call To Action: なにか実行を呼びかける)ボタンのため、なにを実行するためのボタン(購入、とか開発者側が押させたいボタン)です。セカンダリはCTA以外です(キャンセル、とか開発者側は押させたくないけど、ないとダメだよねというボタン)。
Material3的には、OutlinedButtonとElevatedButtonではなく、FilledButtonのデフォルトとtonalで使い分けていくのかな。
まとめ
Material 3 を使ったときのボタン、特にFilledButtonを見てきました。
ElevatedButtonとOutlinedButtonの角がデフォルトではとんがっているので、いつも角丸の設定にしていました。FilledButtonでその設定は不要になりました。
あとは、角を少し丸くするか、横側を半円にするか、の選択ですね。どっちがいいんだろ。
参考
全ソース
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var _brightness = Brightness.light;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
useMaterial3: true,
//primarySwatch: Colors.red,
colorSchemeSeed: Colors.red,
brightness: _brightness,
),
home: MyHomePage(
title: 'Flutter Demo Home Page',
changeBrightness: changeBrightness,
),
);
}
void changeBrightness() {
setState(() {
_brightness =
_brightness == Brightness.light ? Brightness.dark : Brightness.light;
});
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage(
{Key? key, required this.title, required this.changeBrightness})
: super(key: key);
final String title;
final void Function() changeBrightness;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _radioValue = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: SingleChildScrollView(
child: Column(
children: [
FilledButton(onPressed: () {}, child: Text('FilledButton')),
FilledButton.tonal(
onPressed: () {},
child: Text('FilledButton.tonal'),
),
FilledButton(
onPressed: null, child: Text('FilledButton disabled')),
FilledButton.tonal(
onPressed: null,
child: Text('FilledButton.tonal disabled'),
),
FilledButton.icon(
onPressed: () {},
icon: Icon(Icons.add),
label: Text('FilledButton.icon'),
),
FilledButton.tonalIcon(
onPressed: () {},
icon: Icon(Icons.add),
label: Text('FilledButton.tonalIcon'),
),
FilledButton(
onPressed: () {},
child: Text(
'LargeFont',
style: TextStyle(fontSize: 48),
)),
Divider(),
ElevatedButton(onPressed: () {}, child: Text('ElevatedButton')),
OutlinedButton(onPressed: () {}, child: Text('OutlinedButton')),
TextButton(onPressed: () {}, child: Text('TextButton')),
Text('Just text (Not Button)'),
Checkbox(value: true, onChanged: (_) {}),
TextField(),
Switch(value: true, onChanged: (_) {}),
DropdownMenu<int>(
dropdownMenuEntries: [1, 2, 3]
.map((e) =>
DropdownMenuEntry(value: e, label: e.toString()))
.toList()),
Radio(
value: true,
groupValue: _radioValue,
onChanged: (_) {},
)
],
),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.dark_mode), onPressed: widget.changeBrightness),
);
}
}