Flutter 如何设置下拉按钮';以编程方式实现s值?
例如,为了设置Flutter 如何设置下拉按钮';以编程方式实现s值?,flutter,Flutter,例如,为了设置TextFormField中的文本,我可以使用TextEditingController: textEditingController = TextEditingController() ... TextFormField( controller: textEditingController ); ... textEditingController.text = 'my text'; // This is where I can set the text in the Te
TextFormField
中的文本,我可以使用TextEditingController
:
textEditingController = TextEditingController()
...
TextFormField(
controller: textEditingController
);
...
textEditingController.text = 'my text'; // This is where I can set the text in the TextFormField
是否有类似的方法以编程方式在
下拉按钮中设置选择?据我所知,仅仅在下拉按钮中设置值
字段是不够的,因为如果不从包装状态
对象调用设置状态
,就无法应用更改,此处似乎没有快捷方式,必须调用设置状态
,以反映下拉按钮
所选值中的更改。问题是,setState
是受保护的,所以我需要遍历一些循环,以确保在需要时调用它。我最终实现了一个通知程序,DropdownButton
的状态将是它的侦听器。大致如下:
class MyStatefulWidget extends StatefulWidget {
final _valueNotifier = ValueNotifier<String>(null);
@override
State<StatefulWidget> createState() => MyState(_valueNotifier);
// This exposes the ability to change the DropdownButtons's value
void setDropdownValue(String value) {
// This will notify the state and will eventually call setState
_valueNotifier.value = value;
}
}
class MyState extends State<MyStatefulWidget> {
String _selection;
MyState(ValueNotifier<String> valueNotifier) {
valueNotifier.addListener(() {
setState(() {
_selection = valueNotifier.value;
});
});
}
@override
Widget build(BuildContext context) {
return DropdownButton<String>(
items: [
DropdownMenuItem<String>(
value: "1",
child: Text(
"1",
),
),
DropdownMenuItem<String>(
value: "2",
child: Text(
"2",
),
)
],
onChanged: (value) {
setState(() {
_selection = value;
});
},
value: _selection,
);
}
}
类MyStatefulWidget扩展StatefulWidget{
最终_valueNotifier=valueNotifier(null);
@凌驾
State createState()=>MyState(_valueNotifier);
//这暴露了更改DropdownButtons值的能力
void setDropdownValue(字符串值){
//这将通知状态,并最终调用setState
_valueNotifier.value=值;
}
}
类MyState扩展状态{
字符串选择;
MyState(ValueNotifier ValueNotifier){
valueNotifier.addListener((){
设置状态(){
_选择=valueNotifier.value;
});
});
}
@凌驾
小部件构建(构建上下文){
返回下拉按钮(
项目:[
下拉菜单项(
值:“1”,
子:文本(
"1",
),
),
下拉菜单项(
值:“2”,
子:文本(
"2",
),
)
],
一旦更改:(值){
设置状态(){
_选择=价值;
});
},
值:_选择,
);
}
}
如果将逻辑与用户界面分离,并通过用户界面监听的流传递事件,则可以使用setState四处走动,并且逻辑更易于使用
StreamBuilder是一个很棒的小部件,如果您习惯了使用它,它可以大大简化ui代码。本质上,每次新值通过流时,构建器函数都会重新运行,并且可以在snapshot.data中找到放入流中的任何内容,如新的下拉按钮值
下面是一个例子:
在您的ui中,您可以像这样构建下拉按钮:
StreamBuilder<String>(
stream: logicClass.dropdownValueStream,
builder: (context, snapshot) {
return DropdownButton(
items: logicClass.menuItems,
onChanged: logicClass.selectItem,
value: snapshot.data,
);
})
StreamController<String> _dropDownController = StreamController<String>();
Stream<String> get dropdownValueStream => _dropDownController.stream;
Function get selectItem => _dropDownController.sink.add;
SimpleDropdownButton(
values: _values,
itemBuilder: (value) => Text(value),
controller: _controller,
onChanged: (value) => print(_controller.value),
)
StreamBuilder(
流:logicClass.dropdownValueStream,
生成器:(上下文,快照){
返回下拉按钮(
项目:logicClass.menuItems,
一旦更改:logicClass.selectItem,
值:snapshot.data,
);
})
在logic类中,您将构建如下流:
StreamBuilder<String>(
stream: logicClass.dropdownValueStream,
builder: (context, snapshot) {
return DropdownButton(
items: logicClass.menuItems,
onChanged: logicClass.selectItem,
value: snapshot.data,
);
})
StreamController<String> _dropDownController = StreamController<String>();
Stream<String> get dropdownValueStream => _dropDownController.stream;
Function get selectItem => _dropDownController.sink.add;
SimpleDropdownButton(
values: _values,
itemBuilder: (value) => Text(value),
controller: _controller,
onChanged: (value) => print(_controller.value),
)
StreamController\u dropDownController=StreamController();
Stream get dropdownValueStream=>\u dropDownController.Stream;
函数get-selectItem=>\u-dropDownController.sink.add;
最后,如果您想对这些数据执行任何操作,可以在数据通过流时将其存储在逻辑类中。这本质上是UI逻辑与业务逻辑或Bloc模式的分离 我创建了一个简化的下拉按钮
来使用控制器,它可以这样使用:
StreamBuilder<String>(
stream: logicClass.dropdownValueStream,
builder: (context, snapshot) {
return DropdownButton(
items: logicClass.menuItems,
onChanged: logicClass.selectItem,
value: snapshot.data,
);
})
StreamController<String> _dropDownController = StreamController<String>();
Stream<String> get dropdownValueStream => _dropDownController.stream;
Function get selectItem => _dropDownController.sink.add;
SimpleDropdownButton(
values: _values,
itemBuilder: (value) => Text(value),
controller: _controller,
onChanged: (value) => print(_controller.value),
)
基本上,SimpleDropdownButton
包装了一个DropdownButton
,并根据接收到的值列表和您希望显示这些值的方式来处理其DropdownItems
的创建
如果不设置控制器,则使用setState()
的SimpleDropdownButton
将像处理DropdownButton
一样处理所选值
如果确实设置了控制器,则SimpleDropdownButton
开始侦听控制器,以了解何时调用setState()
更新所选值。因此,如果有人选择一个项目(onChanged
),那么SimpleDropdownButton
将不会调用setState()
,而是将新值设置到控制器,控制器将通知侦听器,其中一个侦听器是SimpleDropdownButton
,他将调用setState()
更新所选值。这样,如果您为控制器设置了一个新值,SimpleDropdownButton
将收到通知。此外,由于值始终存储在控制器上,因此可以随时访问
这是实现,您可能希望将更多参数传递到下拉按钮
:
class SimpleDropdownButton<T> extends StatefulWidget {
final List<T> values;
final Widget Function(T value) itemBuilder;
final SimpleDropdownButtonController<T> controller;
final ValueChanged onChanged;
SimpleDropdownButton(
{this.controller,
@required this.values,
@required this.itemBuilder,
this.onChanged});
@override
_SimpleDropdownButtonState<T> createState() =>
_SimpleDropdownButtonState<T>();
}
class _SimpleDropdownButtonState<T> extends State<SimpleDropdownButton<T>> {
T _value;
@override
void initState() {
super.initState();
if (widget.controller != null) {
_value = widget.controller.value;
widget.controller.addListener(() => setState(() {
_value = widget.controller.value;
}));
}
}
@override
void dispose() {
widget.controller?.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return DropdownButton(
value: _value,
items: widget.values
.map((value) => DropdownMenuItem(
value: value,
child: widget.itemBuilder(value),
))
.toList(),
onChanged: (value) {
if (widget.controller != null) {
widget.controller.value = value;
} else {
setState(() {
_value = value;
});
}
widget.onChanged?.call(value);
},
);
}
}
class SimpleDropdownButtonController<T> {
List<VoidCallback> _listeners = [];
T _value;
SimpleDropdownButtonController([this._value]);
get value => _value;
set value(T value) {
_value = value;
_listeners?.forEach((listener) => listener());
}
void addListener(VoidCallback listener) => _listeners.add(listener);
void close() => _listeners?.clear();
}
这是更改下拉按钮
值的唯一方法,您必须使用新值调用setState
。