Flutter 颤振中相应的DropDownButtonFormFields

Flutter 颤振中相应的DropDownButtonFormFields,flutter,dropdownbutton,Flutter,Dropdownbutton,我正在实现相应的下拉列表(其中第二个下拉列表的选项取决于第一个下拉列表),它使用以下格式的对象列表: List<State> states = [ new State(stateId: 1, stateName: "New York", cities: [ new City(cityId: 1, cityName: "New York City"), new City(cityId: 2, cityName: "B

我正在实现相应的下拉列表(其中第二个下拉列表的选项取决于第一个下拉列表),它使用以下格式的对象列表:

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") ...
列表状态=[
纽约州(州号:1,州名:“纽约”,城市:[
纽约市(城市ID:1,城市名称:“纽约市”),
新城(城市ID:2,城市名称:“布法罗”)。。。
小部件代码如下所示:

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;
                    });
                  },
                )
              ],
儿童:[
下拉按钮窗体字段(
装饰:输入装饰(labelText:“状态”),
值:selectedStateId,
项目:states.map((State-State){
返回新的DropdownMenuItem(
值:state.stateId,
子级:新文本(states.singleWhere((x)=>x.stateId==state.stateId.stateName),
);
}).toList(),
一旦更改:(int newStateId){
设置状态(){
this.selectedCityId=states.singleWhere((x)=>x.stateId==newStateId)。城市[0]。cityId;//设置为此状态的第一个城市
this.selectedStateId==newStateId;
});
},
),
下拉按钮窗体字段(
装饰:输入装饰(标签文本:“城市”),
值:selectedCityId,
条目:states.singleWhere((x)=>x.stateId==selectedStateId)
.城市
.map((城市){
返回新的DropdownMenuItem(
值:city.cityId,
儿童:新案文(国家)
.singleWhere((x)=>x.stateId==selectedStateId).cities.singleWhere((x)=>x.cityId==city.cityId).cityName),
);
}).toList(),
一旦更改:(int newCityId){
设置状态(){
this.selectedCityId=newCityId;
});
},
)
],
在本例中,当我更改“状态”下拉列表时,我得到一个错误: “应该只有一个项目具有[DropdownButton]的值:1。 检测到零个或2个或更多具有相同值的[DropdownMenuItem]

“1”在上面的错误中,所选城市值对应于更改状态之前的任何值,因此我知道错误与以下事实有关:它仍然在查找旧的selectedCityId,并且它不再在项目列表中,但我不确定为什么,因为我在setState中更改了该值。我相信,这个问题的关键是相同的cod如果我只是将DropDownButtonForm字段更改为常规DropDownButtons,则e可以工作,但我希望使用前者附带的内置标签文本。

编辑
您可以使用
key:UniqueKey()
int City
DropdownButtonFormField

DropdownButtonFormField<int>(
      key: UniqueKey(),
      decoration: InputDecoration(labelText: 'City'),
工作演示

完整代码

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),
      ),
    );
  }
}
导入“包装:颤振/材料.省道”;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
视觉密度:视觉密度。自适应平台密度,
),
主页:MyHomePage(标题:“颤振演示主页”),
);
}
}
类MyHomePage扩展StatefulWidget{
MyHomePage({Key,this.title}):超级(Key:Key);
最后的字符串标题;
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
阶级城市{
国际城市ID;
字符串cityName;
城市({this.cityId,this.cityName});
}
国家级{
int stateId;
字符串stateName;
列出城市;
CountryState({this.stateId,this.stateName,this.cities});
}
类_MyHomePageState扩展状态{
int _计数器=0;
void _incrementCounter(){
设置状态(){
_计数器++;
});
}
列表状态=[
CountryState(州号:1,州名:“约克”,城市:[
城市(城市ID:1,城市名称:“约克市”),
城市(城市ID:2,城市名称:“布法罗”)
]),
CountryState(州ID:2,州名称:“A”,城市:[
城市(城市ID:3,城市名称:“A1”),
城市(城市ID:4,城市名称:“A2”)
])
];
int-selectedStateId;
int-selectedCityId;
@凌驾
void initState(){
selectedStateId=状态[0]。状态ID;
selectedCityId=州[0]。城市[0]。城市ID;
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(widget.title),
),
正文:中(
子:列(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
下拉按钮窗体字段(
装饰:输入装饰(labelText:“状态”),
值:selectedStateId,
项目:states.map((CountryState){
返回下拉菜单项(
值:state.stateId,
儿童:文本(国家)
.singleWhere((x)=>x.stateId==state.stateId)
(州名称),
);
}).toList(),
一旦更改:(int StateId){
设置状态(){
this.selectedCityId=状态
.singleWhere((x)=>x.stateId==stateId)
.城市[0]
.cityId;//设置为此状态的第一个城市
this.selectedStateId=StateId;
});
},
),
下拉按钮窗体字段(
键:UniqueKey(),
装饰:输入装饰(标签文本:“城市”),
值:selectedCityId,
项目:国家
.singleWhere((x)=>x.stateId==selectedStateId)
.城市
.map((城市){
返回下拉菜单项(
弗吉尼亚州
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),
      ),
    );
  }
}