![](/img/trans.png)
[英]Flutter: how can I make a rounded PopupMenuButton's InkWell?
[英]How to make a reusable PopupMenuButton in Flutter
我想在flutter中制作一個可重用的PopupMenuButton,這樣我就可以調用該小部件並動態分配PopupMenuItem。
這是我所做的,但它引發了框架錯誤。 我在顫振方面相對較新。
這是應該可重用的類:
class PopupMenu {
PopupMenu({@required this.title, @required this.onTap});
final String title;
final VoidCallback onTap;
}
class PopupmMenuButtonBuilder {
setPopup(List<PopupMenu> popupItem) {
return PopupMenuButton<String>(
onSelected: (_) {
popupItem.forEach((item) => item.onTap);
},
itemBuilder: (BuildContext context) {
popupItem.forEach(
(item) {
return <PopupMenuItem<String>>[
PopupMenuItem<String>(
value: item.title,
child: Text(
item.title,
),
),
];
},
);
},
);
}
}
然后我像這樣調用小部件:
child: PopupmMenuButtonBuilder().setPopup([
PopupMenu(title: 'Item 1', onTap: () => print('item 1 selected')),
PopupMenu(title: 'Item 2', onTap: () => print('item 2 selected')),
]),
它顯示了 3 點圖標按鈕,但是當我點擊該圖標時,它會引發此錯誤:
I/flutter ( 8509): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter ( 8509): The following assertion was thrown while handling a gesture:
I/flutter ( 8509): 'package:flutter/src/material/popup_menu.dart': Failed assertion: line 723 pos 10: 'items != null &&
I/flutter ( 8509): items.isNotEmpty': is not true.
I/flutter ( 8509): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter ( 8509): more information in this error message to help you determine and fix the underlying cause.
I/flutter ( 8509): In either case, please report this assertion by filing a bug on GitHub:
I/flutter ( 8509): https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter ( 8509): When the exception was thrown, this was the stack:
I/flutter ( 8509): #2 showMenu (package:flutter/src/material/popup_menu.dart:723:10)
I/flutter ( 8509): #3 _PopupMenuButtonState.showButtonMenu (package:flutter/src/material/popup_menu.dart:898:5)
I/flutter ( 8509): #4 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:511:14)
I/flutter ( 8509): #5 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:566:30)
I/flutter ( 8509): #6 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:166:24)
I/flutter ( 8509): #7 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:240:9)
I/flutter ( 8509): #8 TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:211:7)
I/flutter ( 8509): #9 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
I/flutter ( 8509): #10 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:225:20)
I/flutter ( 8509): #11 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:199:22)
I/flutter ( 8509): #12 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
I/flutter ( 8509): #13 _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)I/flutter ( 8509): #14 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)I/flutter ( 8509): #18 _invoke1 (dart:ui/hooks.dart:233:10)
I/flutter ( 8509): #19 _dispatchPointerDataPacket (dart:ui/hooks.dart:154:5)
I/flutter ( 8509): (elided 5 frames from class _AssertionError and package dart:async)
I/flutter ( 8509): Handler: onTap
I/flutter ( 8509): Recognizer:
I/flutter ( 8509): TapGestureRecognizer#8968f(debugOwner: GestureDetector, state: ready, won arena, finalPosition:
I/flutter ( 8509): Offset(339.0, 54.0), sent tap down)
I/flutter ( 8509): ════════════════════════════════════════════════════════════════════════════════════════════════════
您的itemBuilder
需要返回一個List
。 它實際上並沒有返回任何東西——注意return
是如何在forEach
內部的,所以它只是從 lambda 返回。 一般來說,有時應該避免forEach
。 此外, PopupMenuButtonBuilder
類是多余的 - 它可以用靜態或頂級函數替換。
另一件不清楚的事情是為什么要為每個選擇調用每個onTap
。 正如您目前擁有的那樣,它將調用每個回調!
嘗試這個:
class PopupMenu {
PopupMenu({@required this.title, @required this.onTap});
final String title;
final VoidCallback onTap;
static PopupMenuButton<String> createPopup(List<PopupMenu> popupItems) {
return PopupMenuButton<String>(
onSelected: (value) {
popupItems.firstWhere((e) => e.title == value).onTap();
},
itemBuilder: (context) => popupItems
.map((item) => PopupMenuItem<String>(
value: item.title,
child: Text(
item.title,
),
))
.toList(),
);
}
}
您還可以創建一個可變列表附加到彈出菜單,而不是在子項中手動創建它
child: PopupMenu(popUpList: _popUpList).createPopup()),
然后在彈出菜單類中
class PopupMenu {
const PopupMenu({this.popUpList});
final List<PopUpList> popUpList;
PopupMenuButton<String> createPopup() {
return PopupMenuButton<String>(
onSelected: (value) {
popUpList.firstWhere((e) => e.title == value).onTap();
},
itemBuilder: (context) => popUpList
.map((item) => PopupMenuItem<String>(
value: item.title,
child: Text(item.title),
)).toList(),
);
}
}
模型
class PopUpList{
String title;
VoidCallback onTap;
PopUpList({this.onTap, this.title});
}
干杯!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.