如何在弹出菜单中使用单选按钮?
How do I use radio buttons inside popup menus?
我正在尝试创建一个包含可选单选按钮的弹出菜单,以便更改视图类型(例如图库、卡片、滑动、网格、列表等)。
我 运行 遇到的问题是 PopupMenu 有自己的回调来选择值,Radio 和 RadioListTile 也是如此。
忽略 RadioListTile 的 onChanged
这是我的第一次尝试。这确实有效,除了按钮永远变灰。为 RadioListTiles 提供一个非 null noop 函数会导致按钮不再变灰(禁用),但弹出菜单不再有效。
new PopupMenuButton<String>(
...
itemBuilder: (ctx) => <PopupMenuEntry<String>>[
new PopupMenuItem(
child: new RadioListTile(
title: new Text("Cards"),
value: 'cards',
groupValue: _view,
onChanged: null),
value: 'cards'),
new PopupMenuItem(
child: new RadioListTile(
title: new Text("Swipe"),
value: 'swipe',
groupValue: _view,
onChanged: null),
value: 'swipe'),
],
onSelected: (String viewType) {
_view = viewType;
}));
使用 RadioListTile,忽略 PopupMenu
第二次尝试是完全忽略 PopupMenu,只使用 RadioListTile onChanged
。这些按钮不是 grayed-out/disabled,但也不起作用。
new PopupMenuButton<String>(
...
itemBuilder: (ctx) => <PopupMenuEntry<Null>>[
new PopupMenuItem(
child: new RadioListTile(
title: new Text("Cards"),
value: 'cards',
groupValue: _view,
onChanged: (v) => setState(() => _view = v)),
value: 'cards'),
new PopupMenuItem(
child: new RadioListTile(
title: new Text("Swipe"),
value: 'swipe',
groupValue: _view,
onChanged: (v) => setState(() => _view = v)),
value: 'swipe'),
],
));
正确的做法是什么? PopupMenu 适用于极其简单的菜单,但元素选择给我带来了冲突。有没有办法获得 "dumb" 弹出菜单,在按钮处显示一列小部件(样式像菜单)?
我认为最适合您的解决方案是使用 CheckedPopupMenuItems 而不是广播列表。该功能应该正是您想要实现的,不是吗?
这是一个小例子:
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _selectedView = 'Card';
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('TestProject'),
actions: <Widget>[
new PopupMenuButton(
onSelected: (value) => setState(() => _selectedView = value),
itemBuilder: (_) => [
new CheckedPopupMenuItem(
checked: _selectedView == 'Card',
value: 'Card',
child: new Text('Card'),
),
new CheckedPopupMenuItem(
checked: _selectedView == 'Swipe',
value: 'Swipe',
child: new Text('Swipe'),
),
new CheckedPopupMenuItem(
checked: _selectedView == 'List',
value: 'List',
child: new Text('List'),
),
],
),
],
),
body: new Center(child: new Text(_selectedView)),
);
}
}
问题是 PopupMenuButton
is maintaining the popup dialog as private state (it even pushes a new route onto the Navigator
stack). Calling setState
won't rebuild the items. You can use an AnimatedBuilder
and a ValueNotifier
解决这个问题。
这是弹出窗口中有效单选按钮列表的示例:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
State createState() => new MyHomePageState();
}
enum Fruit {
apple,
banana,
}
class MyHomePageState extends State<MyHomePage> {
ValueNotifier<Fruit> _selectedItem = new ValueNotifier<Fruit>(Fruit.apple);
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new PopupMenuButton<Fruit>(
itemBuilder: (BuildContext context) {
return new List<PopupMenuEntry<Fruit>>.generate(
Fruit.values.length,
(int index) {
return new PopupMenuItem(
value: Fruit.values[index],
child: new AnimatedBuilder(
child: new Text(Fruit.values[index].toString()),
animation: _selectedItem,
builder: (BuildContext context, Widget child) {
return new RadioListTile<Fruit>(
value: Fruit.values[index],
groupValue: _selectedItem.value,
title: child,
onChanged: (Fruit value) {
_selectedItem.value = value;
},
);
},
),
);
},
);
},
),
),
);
}
}
我正在尝试创建一个包含可选单选按钮的弹出菜单,以便更改视图类型(例如图库、卡片、滑动、网格、列表等)。
我 运行 遇到的问题是 PopupMenu 有自己的回调来选择值,Radio 和 RadioListTile 也是如此。
忽略 RadioListTile 的 onChanged
这是我的第一次尝试。这确实有效,除了按钮永远变灰。为 RadioListTiles 提供一个非 null noop 函数会导致按钮不再变灰(禁用),但弹出菜单不再有效。
new PopupMenuButton<String>(
...
itemBuilder: (ctx) => <PopupMenuEntry<String>>[
new PopupMenuItem(
child: new RadioListTile(
title: new Text("Cards"),
value: 'cards',
groupValue: _view,
onChanged: null),
value: 'cards'),
new PopupMenuItem(
child: new RadioListTile(
title: new Text("Swipe"),
value: 'swipe',
groupValue: _view,
onChanged: null),
value: 'swipe'),
],
onSelected: (String viewType) {
_view = viewType;
}));
使用 RadioListTile,忽略 PopupMenu
第二次尝试是完全忽略 PopupMenu,只使用 RadioListTile onChanged
。这些按钮不是 grayed-out/disabled,但也不起作用。
new PopupMenuButton<String>(
...
itemBuilder: (ctx) => <PopupMenuEntry<Null>>[
new PopupMenuItem(
child: new RadioListTile(
title: new Text("Cards"),
value: 'cards',
groupValue: _view,
onChanged: (v) => setState(() => _view = v)),
value: 'cards'),
new PopupMenuItem(
child: new RadioListTile(
title: new Text("Swipe"),
value: 'swipe',
groupValue: _view,
onChanged: (v) => setState(() => _view = v)),
value: 'swipe'),
],
));
正确的做法是什么? PopupMenu 适用于极其简单的菜单,但元素选择给我带来了冲突。有没有办法获得 "dumb" 弹出菜单,在按钮处显示一列小部件(样式像菜单)?
我认为最适合您的解决方案是使用 CheckedPopupMenuItems 而不是广播列表。该功能应该正是您想要实现的,不是吗?
这是一个小例子:
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _selectedView = 'Card';
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('TestProject'),
actions: <Widget>[
new PopupMenuButton(
onSelected: (value) => setState(() => _selectedView = value),
itemBuilder: (_) => [
new CheckedPopupMenuItem(
checked: _selectedView == 'Card',
value: 'Card',
child: new Text('Card'),
),
new CheckedPopupMenuItem(
checked: _selectedView == 'Swipe',
value: 'Swipe',
child: new Text('Swipe'),
),
new CheckedPopupMenuItem(
checked: _selectedView == 'List',
value: 'List',
child: new Text('List'),
),
],
),
],
),
body: new Center(child: new Text(_selectedView)),
);
}
}
问题是 PopupMenuButton
is maintaining the popup dialog as private state (it even pushes a new route onto the Navigator
stack). Calling setState
won't rebuild the items. You can use an AnimatedBuilder
and a ValueNotifier
解决这个问题。
这是弹出窗口中有效单选按钮列表的示例:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
State createState() => new MyHomePageState();
}
enum Fruit {
apple,
banana,
}
class MyHomePageState extends State<MyHomePage> {
ValueNotifier<Fruit> _selectedItem = new ValueNotifier<Fruit>(Fruit.apple);
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new PopupMenuButton<Fruit>(
itemBuilder: (BuildContext context) {
return new List<PopupMenuEntry<Fruit>>.generate(
Fruit.values.length,
(int index) {
return new PopupMenuItem(
value: Fruit.values[index],
child: new AnimatedBuilder(
child: new Text(Fruit.values[index].toString()),
animation: _selectedItem,
builder: (BuildContext context, Widget child) {
return new RadioListTile<Fruit>(
value: Fruit.values[index],
groupValue: _selectedItem.value,
title: child,
onChanged: (Fruit value) {
_selectedItem.value = value;
},
);
},
),
);
},
);
},
),
),
);
}
}