相信在實際開發過程當中,肯定少不了這樣的功能:
點選 AppBar
右上角的按鈕,彈出一個選單供使用者選擇。
幸運的是,Flutter 提供給我們了一個 Widget,直接就能實現如上的效果。
PopupMenuButton
還是老規矩,先看官方的說明:
Displays a menu when pressed and calls onSelected when the menu is dismissed because an item was selected. The value passed to onSelected is the value of the selected menu item.
One of child or icon may be provided, but not both. If icon is provided, then PopupMenuButton behaves like an IconButton.
If both are null, then a standard overflow icon is created (depending on the platform).
大致意思為:
當按下的時候顯示一個選單,選擇了一個專案的時候會回撥
onSelected
,傳遞的值是所選選單的值。可以提供
child
oricon
,但是不能同時提供。如果為空,則提供一個預設的圖示,取決於平臺。
建構函式
看完了官方說明,再來看建構函式:
const PopupMenuButton({
Key key,
@required this.itemBuilder,
this.initialValue,
this.onSelected,
this.onCanceled,
this.tooltip,
this.elevation = 8.0,
this.padding = const EdgeInsets.all(8.0),
this.child,
this.icon,
this.offset = Offset.zero,
this.enabled = true,
}) : assert(itemBuilder != null),
assert(offset != null),
assert(enabled != null),
assert(!(child != null && icon != null)), // fails if passed both parameters
super(key: key);
複製程式碼
這裡面每一個引數應該都很好理解,就不做過多的解釋了,
唯一必傳的引數就是 itemBuilder
,也可以看到後面的斷言:
assert(!(child != null && icon != null))
判斷了 child 、icon 是否同時不為空,如果是的話就報錯了。
簡單 Demo
建構函式理解了,官方也提供了一個 Demo,我們來看一下執行效果:
再來看一下程式碼:
/// 首先定義了一個列舉
enum WhyFarther {
harder,
smarter,
selfStarter,
tradingCharter,
}
/// ------------------------------------
/// build 方法
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('PopupMenuButtonPage'),
actions: <Widget>[
PopupMenuButton<WhyFarther>(
onSelected: (WhyFarther result) {
setState(() {
_selection = result;
});
},
icon: Icon(Icons.more_vert),
itemBuilder: (BuildContext context) => <PopupMenuEntry<WhyFarther>>[
const PopupMenuItem<WhyFarther>(
value: WhyFarther.harder,
child: Text('Working a lot harder'),
),
const PopupMenuItem<WhyFarther>(
value: WhyFarther.smarter,
child: Text('Being a lot smarter'),
),
const PopupMenuItem<WhyFarther>(
value: WhyFarther.selfStarter,
child: Text('Being a self-starter'),
),
const PopupMenuItem<WhyFarther>(
value: WhyFarther.tradingCharter,
child: Text('Placed in charge of trading charter'),
),
],
),
],
),
body: Container(),
);
}
複製程式碼
解釋一下邏輯:
- 首先定義了一個列舉
- 然後在
AppBar
的「actions」裡定義了PopupMenuButton
- 設定 icon 為
Icon(Icons.more_vert)
itemBuilder
需返回一個List<PopupMenuEntry<T>>
- 這裡傳入的值就是
PopupMenuItem<WhyFarther>
- 然後定義
onSelected
引數接收點選回撥
這樣整體的邏輯就是定義好了,執行一下:
總結
這樣就完成了一個超級簡單並且實用的選單彈出框,
其實它的實現邏輯和 DropdownButton
差不多,都是使用了 PopupRoute
,
有對這方面感興趣的同學,可以檢視我以前寫的文章:Flutter 原始碼系列:DropdownButton 原始碼淺析
完整程式碼已經傳至GitHub:github.com/wanglu1209/…