Flutter中对应的DropDownButtonFormField
Corresponding DropDownButtonFormFields in Flutter
我正在实现相应的下拉菜单(其中第二个下拉菜单的选项取决于第一个下拉菜单),它使用以下格式的对象列表:
List<State> states = [
new State(stateId: 1, stateName: "New York", cities: [
new City(cityId: 1, cityName: "New York City"),
new City(cityId: 2, cityName: "Buffalo") ...
小部件代码如下:
children: <Widget>[
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'State'),
value: selectedStateId,
items: states.map((State state) {
return new DropdownMenuItem<int>(
value: state.stateId,
child: new Text(states.singleWhere((x) => x.stateId == state.stateId).stateName),
);
}).toList(),
onChanged: (int newStateId) {
setState(() {
this.selectedCityId = states.singleWhere((x) => x.stateId == newStateId).cities[0].cityId; // set to first city for this state
this.selectedStateId = = newStateId;
});
},
),
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'City'),
value: selectedCityId,
items: states.singleWhere((x) => x.stateId == selectedStateId)
.cities
.map((City city) {
return new DropdownMenuItem<int>(
value: city.cityId,
child: new Text(states
.singleWhere((x) => x.stateId == selectedStateId).cities.singleWhere((x) => x.cityId == city.cityId).cityName),
);
}).toList(),
onChanged: (int newCityId) {
setState(() {
this.selectedCityId = newCityId;
});
},
)
],
当我在此示例中更改状态下拉列表时,出现错误:
“应该只有一项具有 [DropdownButton] 的值:1。
检测到具有相同值的零个或两个或更多 [DropdownMenuItem]。
上述错误中的“1”对应于更改状态之前所选城市的值,所以我知道该错误与它仍在寻找旧的 selectedCityId 而不再是在项目列表中,但我不确定为什么我在 setState 中更改了该值。我认为,这个问题的一个关键是,如果我只是将 DropDownButtonFormField 更改为常规 DropDownButtons,则完全相同的代码仍然有效,但我想使用前者附带的内置标签文本。
编辑
您可以使用 key: UniqueKey()
int City DropdownButtonFormField
DropdownButtonFormField<int>(
key: UniqueKey(),
decoration: InputDecoration(labelText: 'City'),
您可以复制粘贴运行下面的完整代码
您可以将 selectedStateId
和 selectedCityId
设置为 states
的属性
不能直接设置成selectedStateId = 1
这样的值,因为系统会比较地址
代码片段
int selectedStateId;
int selectedCityId;
@override
void initState() {
selectedStateId = states[0].stateId;
selectedCityId = states[0].cities[0].cityId;
super.initState();
}
工作演示
完整代码
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class City {
int cityId;
String cityName;
City({this.cityId, this.cityName});
}
class CountryState {
int stateId;
String stateName;
List<City> cities;
CountryState({this.stateId, this.stateName, this.cities});
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
List<CountryState> states = [
CountryState(stateId: 1, stateName: " York", cities: [
City(cityId: 1, cityName: "York City"),
City(cityId: 2, cityName: "Buffalo")
]),
CountryState(stateId: 2, stateName: "A", cities: [
City(cityId: 3, cityName: "A1"),
City(cityId: 4, cityName: "A2")
])
];
int selectedStateId;
int selectedCityId;
@override
void initState() {
selectedStateId = states[0].stateId;
selectedCityId = states[0].cities[0].cityId;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'State'),
value: selectedStateId,
items: states.map((CountryState state) {
return DropdownMenuItem<int>(
value: state.stateId,
child: Text(states
.singleWhere((x) => x.stateId == state.stateId)
.stateName),
);
}).toList(),
onChanged: (int StateId) {
setState(() {
this.selectedCityId = states
.singleWhere((x) => x.stateId == StateId)
.cities[0]
.cityId; // set to first city for this state
this.selectedStateId = StateId;
});
},
),
DropdownButtonFormField<int>(
key: UniqueKey(),
decoration: InputDecoration(labelText: 'City'),
value: selectedCityId,
items: states
.singleWhere((x) => x.stateId == selectedStateId)
.cities
.map((City city) {
return DropdownMenuItem<int>(
value: city.cityId,
child: Text(states
.singleWhere((x) => x.stateId == selectedStateId)
.cities
.singleWhere((x) => x.cityId == city.cityId)
.cityName),
);
}).toList(),
onChanged: (int CityId) {
setState(() {
this.selectedCityId = CityId;
});
},
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
我在 Flutter 问题板上发布了这个示例,它们无法在最新的稳定版本(截至本评论时为 1.20.2)上复制。我升级了我的 flutter 版本(我在 1.17.1)和相同的代码 运行 没有问题,所以对于遇到同样问题的任何人我建议更新你的 flutter 版本。
我正在实现相应的下拉菜单(其中第二个下拉菜单的选项取决于第一个下拉菜单),它使用以下格式的对象列表:
List<State> states = [
new State(stateId: 1, stateName: "New York", cities: [
new City(cityId: 1, cityName: "New York City"),
new City(cityId: 2, cityName: "Buffalo") ...
小部件代码如下:
children: <Widget>[
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'State'),
value: selectedStateId,
items: states.map((State state) {
return new DropdownMenuItem<int>(
value: state.stateId,
child: new Text(states.singleWhere((x) => x.stateId == state.stateId).stateName),
);
}).toList(),
onChanged: (int newStateId) {
setState(() {
this.selectedCityId = states.singleWhere((x) => x.stateId == newStateId).cities[0].cityId; // set to first city for this state
this.selectedStateId = = newStateId;
});
},
),
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'City'),
value: selectedCityId,
items: states.singleWhere((x) => x.stateId == selectedStateId)
.cities
.map((City city) {
return new DropdownMenuItem<int>(
value: city.cityId,
child: new Text(states
.singleWhere((x) => x.stateId == selectedStateId).cities.singleWhere((x) => x.cityId == city.cityId).cityName),
);
}).toList(),
onChanged: (int newCityId) {
setState(() {
this.selectedCityId = newCityId;
});
},
)
],
当我在此示例中更改状态下拉列表时,出现错误: “应该只有一项具有 [DropdownButton] 的值:1。 检测到具有相同值的零个或两个或更多 [DropdownMenuItem]。
上述错误中的“1”对应于更改状态之前所选城市的值,所以我知道该错误与它仍在寻找旧的 selectedCityId 而不再是在项目列表中,但我不确定为什么我在 setState 中更改了该值。我认为,这个问题的一个关键是,如果我只是将 DropDownButtonFormField 更改为常规 DropDownButtons,则完全相同的代码仍然有效,但我想使用前者附带的内置标签文本。
编辑
您可以使用 key: UniqueKey()
int City DropdownButtonFormField
DropdownButtonFormField<int>(
key: UniqueKey(),
decoration: InputDecoration(labelText: 'City'),
您可以复制粘贴运行下面的完整代码
您可以将 selectedStateId
和 selectedCityId
设置为 states
的属性
不能直接设置成selectedStateId = 1
这样的值,因为系统会比较地址
代码片段
int selectedStateId;
int selectedCityId;
@override
void initState() {
selectedStateId = states[0].stateId;
selectedCityId = states[0].cities[0].cityId;
super.initState();
}
工作演示
完整代码
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class City {
int cityId;
String cityName;
City({this.cityId, this.cityName});
}
class CountryState {
int stateId;
String stateName;
List<City> cities;
CountryState({this.stateId, this.stateName, this.cities});
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
List<CountryState> states = [
CountryState(stateId: 1, stateName: " York", cities: [
City(cityId: 1, cityName: "York City"),
City(cityId: 2, cityName: "Buffalo")
]),
CountryState(stateId: 2, stateName: "A", cities: [
City(cityId: 3, cityName: "A1"),
City(cityId: 4, cityName: "A2")
])
];
int selectedStateId;
int selectedCityId;
@override
void initState() {
selectedStateId = states[0].stateId;
selectedCityId = states[0].cities[0].cityId;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'State'),
value: selectedStateId,
items: states.map((CountryState state) {
return DropdownMenuItem<int>(
value: state.stateId,
child: Text(states
.singleWhere((x) => x.stateId == state.stateId)
.stateName),
);
}).toList(),
onChanged: (int StateId) {
setState(() {
this.selectedCityId = states
.singleWhere((x) => x.stateId == StateId)
.cities[0]
.cityId; // set to first city for this state
this.selectedStateId = StateId;
});
},
),
DropdownButtonFormField<int>(
key: UniqueKey(),
decoration: InputDecoration(labelText: 'City'),
value: selectedCityId,
items: states
.singleWhere((x) => x.stateId == selectedStateId)
.cities
.map((City city) {
return DropdownMenuItem<int>(
value: city.cityId,
child: Text(states
.singleWhere((x) => x.stateId == selectedStateId)
.cities
.singleWhere((x) => x.cityId == city.cityId)
.cityName),
);
}).toList(),
onChanged: (int CityId) {
setState(() {
this.selectedCityId = CityId;
});
},
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
我在 Flutter 问题板上发布了这个示例,它们无法在最新的稳定版本(截至本评论时为 1.20.2)上复制。我升级了我的 flutter 版本(我在 1.17.1)和相同的代码 运行 没有问题,所以对于遇到同样问题的任何人我建议更新你的 flutter 版本。