PopupMenuButtonのベース実装
ベースとなる最もシンプルなポップアップメニューを作成しました
機能もデザインもシンプルです
popup_menu_button_screen.dart
class PopupMenuButtonScreen extends StatefulWidget {
const PopupMenuButtonScreen({super.key});
@override
State<StatefulWidget> createState() => _PopupMenuButtonScreen();
}
class _PopupMenuButtonScreen extends State<PopupMenuButtonScreen> {
String selectedValue = '月曜日';
final lists = ['月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日', '日曜日'];
Widget build(BuildContext context) {
return Scaffold(
body: Center(
// Sting以外も指定できるよ
child: PopupMenuButton<String>(
child: Text(selectedValue),
itemBuilder: (BuildContext context) {
return lists.map((String list) {
return PopupMenuItem(
value: list,
child: Text(list),
);
}).toList();
},
onSelected: (String list) {
setState(() {
selectedValue = list;
});
},
),
),
);
}
}
PopupMenuButtonの改修
DropdownButtonに比べて自由度が高かったのでPopupMenuButtonの方が扱いやすかったです
分かりにくい設定もほぼなかったので直感的に実装できるのも良かったです
ボタン自体のUIはchild配下で指定できるので他のwidgetとも親和性があっていいかと思います
個人的に一番好きなところは表示されるリストの位置を指定できるとこですね
DropdownButtonでもできるのかもしれないですがこっちの方が確実に楽に設定できます
強いてめんどくさい点を挙げるならiconとchildが一緒に使えないくらいですが、
ほぼ気にならないので問題ないかと思います
入力する系の実装が必要な場合はPopupMenuButtonは使えなそうなのでご注意を
詳しくは公式サイトをご覧ください
https://api.flutter.dev/flutter/material/PopupMenuButton-class.html
popup_menu_button_screen.dart
child: PopupMenuButton<String>(
itemBuilder: (BuildContext context) {
return lists.map((String list) {
return PopupMenuItem(
value: list,
// ポップアップリストをタップした際に行う処理
onTap: () {
debugPrint('ポップアップリストをタップしたよ');
},
// falseにするとタップできなくなるよ
enabled: true,
// 最小値はkMinInteractiveDimensionで指定されているよ(min 48)
height: 60,
// ポップアップリストのpaddingを指定できるよ
padding: EdgeInsets.zero,
// ポップアップリストのTextStyleを指定できるよ
textStyle: const TextStyle(color: Colors.red),
// webでみた時にポップアップリストにフォーカスが当たって時の処理
mouseCursor: MouseCursor.defer,
child: Text(list),
);
}).toList();
},
onSelected: (String list) {
setState(() {
selectedValue = list;
});
},
// 設定さている文字列がリストにあると強調して表示してくれるよ
initialValue: selectedValue,
// ポップアップリストを表示したけど何もせずに閉じた際に行う処理
onCanceled: () {
debugPrint('ポップアップリストを表示したけど何も選択しなかったよ!');
},
// 長押しした時に表示される文言だよ
// webだとクリックした時に表示されるよ
tooltip: '長押しされたよ',
// 影を指定できるよ
elevation: 0,
// childではなくiconを使った時に反映されるよ
padding: const EdgeInsets.all(30),
// PopupMenuButtonをタップした時のエフェクトの半径を指定できるよ
splashRadius: 100,
// childとiconどちらかしか使えないよ
// icon: const Icon(Icons.change_circle),
// アイコンのサイズを指定できるよ
// iconSize: 30,
// ポップアップメニューを表示する位置を指定できるよ
// childを始点にしているので注意
offset: const Offset(10, 100),
// falseにするとタップできなくなるよ
enabled: true,
// ポップアップメニューのレイアウトを指定できるよ
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
// ポップアップメニューの色を指定できるよ
color: Colors.yellow,
// trueだとクリックサウンドを再生できたりするよ(Feedback class参照)
enableFeedback: true,
// ポップアップメニューのサイズを指定できるよ
constraints: const BoxConstraints(
minWidth: 4.0 * 56.0,
maxWidth: 5.0 * 56.0,
),
// ポップアップメニューが表示される位置を指定できるよ
position: PopupMenuPosition.under,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
selectedValue,
),
],
),
),