Flutter:关闭下拉按钮(DropdownMenu)
Flutter: Close DropdownButton (DropdownMenu)
有没有办法在执行 onTap 函数(DropdownMenuItem 内的 GestureDetector)时关闭包含所有 DropdownMenuItem 的 DropdownButton 的选择菜单?
这里是我对 Alperen Baskaya 方法的实现(为了便于理解,略微简化了版本)。然而,这种方法还行不通,我不确定是因为我没有正确实施它,还是因为该方法不适用于我的问题。
class _BoatSelectionState extends State<BoatSelection> {
FocusNode focusNode;
@override
void initState() {
super.initState();
focusNode = FocusNode();
}
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child:
DropdownButtonHideUnderline(
child: DropdownButton<Boat>(
focusNode: focusNode,
icon: Icon(
Icons.keyboard_arrow_down_rounded,
color: Colors.black,
),
isExpanded: true,
value: selectedBoat,
onChanged: (Boat _boat) => Provider.of<BoatStreamsCubit>(context, listen: false).setBoat(_boat),
selectedItemBuilder: (BuildContext context) {
return widget.boats.map<Widget>((Boat boat) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BoatClassLogo(boat: boat),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: DesignValues.paddingMd),
child: BoatInformation(boat: boat),
),
),
],
);
}).toList();
},
items: widget.boats.map<DropdownMenuItem<Boat>>((Boat _boat) {
return DropdownMenuItem<Boat>(
value: _boat,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(right: DesignValues.paddingMd),
child: BoatClassLogo(boat: _boat),
),
Expanded(
child: BoatInformation(boat: _boat),
),
GestureDetector(
onTap: () {
focusNode.unfocus();
Navigator.push(context, MaterialPageRoute(builder: (context) => BoatForm(CreationState.edit, _boat)));
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: Icon(
Icons.edit,
color: AppColors.primary,
),
),
),
],
),
);
}).toList(),
),
),
),
],
);
}
}
如果我没看错,您可以将焦点节点用于下拉菜单。
FocusNode dropdown;
需要在initstate中初始化;
dropdown = FocusNode();
child: DropdownButtonHideUnderline(
child: DropdownButton <String>(
focusNode: dropdown,
然后当你想关闭这个菜单的时候在ontap中执行;
dropdown.unfocus();
我查看了 dart 中下拉菜单的内部实现。下拉菜单的弹出窗口是使用 Navigator.push() 创建的。它等待用户单击一个项目并使用 Navigator.pop() returns 值。所以我们可以通过全局键获取下拉菜单的上下文来手动弹出弹出框。
void initState() {
super.initState();
dropdownKey = GlobalKey();
}
...
DropdownButton<Boat>(
key: dropdownKey,
...
GestureDetector(
onTap: () {
Navigator.pop(dropdownKey.currentContext);
完整代码:
class _BoatSelectionState extends State<BoatSelection> {
GlobalKey dropdownKey;
@override
void initState() {
super.initState();
dropdownKey = GlobalKey(); // Init GlobalKey, allows to close the DropdownButton
}
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child:
DropdownButtonHideUnderline(
child: DropdownButton<Boat>(
key: dropdownKey,
icon: Icon(
Icons.keyboard_arrow_down_rounded,
color: Colors.black,
),
isExpanded: true,
value: selectedBoat,
onChanged: (Boat _boat) => Provider.of<BoatStreamsCubit>(context, listen: false).setBoat(_boat),
selectedItemBuilder: (BuildContext context) {
return widget.boats.map<Widget>((Boat boat) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BoatClassLogo(boat: boat),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: DesignValues.paddingMd),
child: BoatInformation(boat: boat),
),
),
],
);
}).toList();
},
items: widget.boats.map<DropdownMenuItem<Boat>>((Boat _boat) {
return DropdownMenuItem<Boat>(
value: _boat,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(right: DesignValues.paddingMd),
child: BoatClassLogo(boat: _boat),
),
Expanded(
child: BoatInformation(boat: _boat),
),
GestureDetector(
onTap: () {
Navigator.pop(dropdownKey.currentContext); // Closes the dropdown
Navigator.push(context, MaterialPageRoute(builder: (context) => BoatForm(CreationState.edit, _boat)));
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: Icon(
Icons.edit,
color: AppColors.primary,
),
),
),
],
),
);
}).toList(),
),
),
),
],
);
}
}
有没有办法在执行 onTap 函数(DropdownMenuItem 内的 GestureDetector)时关闭包含所有 DropdownMenuItem 的 DropdownButton 的选择菜单?
这里是我对 Alperen Baskaya 方法的实现(为了便于理解,略微简化了版本)。然而,这种方法还行不通,我不确定是因为我没有正确实施它,还是因为该方法不适用于我的问题。
class _BoatSelectionState extends State<BoatSelection> {
FocusNode focusNode;
@override
void initState() {
super.initState();
focusNode = FocusNode();
}
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child:
DropdownButtonHideUnderline(
child: DropdownButton<Boat>(
focusNode: focusNode,
icon: Icon(
Icons.keyboard_arrow_down_rounded,
color: Colors.black,
),
isExpanded: true,
value: selectedBoat,
onChanged: (Boat _boat) => Provider.of<BoatStreamsCubit>(context, listen: false).setBoat(_boat),
selectedItemBuilder: (BuildContext context) {
return widget.boats.map<Widget>((Boat boat) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BoatClassLogo(boat: boat),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: DesignValues.paddingMd),
child: BoatInformation(boat: boat),
),
),
],
);
}).toList();
},
items: widget.boats.map<DropdownMenuItem<Boat>>((Boat _boat) {
return DropdownMenuItem<Boat>(
value: _boat,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(right: DesignValues.paddingMd),
child: BoatClassLogo(boat: _boat),
),
Expanded(
child: BoatInformation(boat: _boat),
),
GestureDetector(
onTap: () {
focusNode.unfocus();
Navigator.push(context, MaterialPageRoute(builder: (context) => BoatForm(CreationState.edit, _boat)));
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: Icon(
Icons.edit,
color: AppColors.primary,
),
),
),
],
),
);
}).toList(),
),
),
),
],
);
}
}
如果我没看错,您可以将焦点节点用于下拉菜单。
FocusNode dropdown;
需要在initstate中初始化;
dropdown = FocusNode();
child: DropdownButtonHideUnderline(
child: DropdownButton <String>(
focusNode: dropdown,
然后当你想关闭这个菜单的时候在ontap中执行;
dropdown.unfocus();
我查看了 dart 中下拉菜单的内部实现。下拉菜单的弹出窗口是使用 Navigator.push() 创建的。它等待用户单击一个项目并使用 Navigator.pop() returns 值。所以我们可以通过全局键获取下拉菜单的上下文来手动弹出弹出框。
void initState() {
super.initState();
dropdownKey = GlobalKey();
}
...
DropdownButton<Boat>(
key: dropdownKey,
...
GestureDetector(
onTap: () {
Navigator.pop(dropdownKey.currentContext);
完整代码:
class _BoatSelectionState extends State<BoatSelection> {
GlobalKey dropdownKey;
@override
void initState() {
super.initState();
dropdownKey = GlobalKey(); // Init GlobalKey, allows to close the DropdownButton
}
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child:
DropdownButtonHideUnderline(
child: DropdownButton<Boat>(
key: dropdownKey,
icon: Icon(
Icons.keyboard_arrow_down_rounded,
color: Colors.black,
),
isExpanded: true,
value: selectedBoat,
onChanged: (Boat _boat) => Provider.of<BoatStreamsCubit>(context, listen: false).setBoat(_boat),
selectedItemBuilder: (BuildContext context) {
return widget.boats.map<Widget>((Boat boat) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BoatClassLogo(boat: boat),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: DesignValues.paddingMd),
child: BoatInformation(boat: boat),
),
),
],
);
}).toList();
},
items: widget.boats.map<DropdownMenuItem<Boat>>((Boat _boat) {
return DropdownMenuItem<Boat>(
value: _boat,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(right: DesignValues.paddingMd),
child: BoatClassLogo(boat: _boat),
),
Expanded(
child: BoatInformation(boat: _boat),
),
GestureDetector(
onTap: () {
Navigator.pop(dropdownKey.currentContext); // Closes the dropdown
Navigator.push(context, MaterialPageRoute(builder: (context) => BoatForm(CreationState.edit, _boat)));
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: Icon(
Icons.edit,
color: AppColors.primary,
),
),
),
],
),
);
}).toList(),
),
),
),
],
);
}
}