Flutter下拉菜单选择不适用于有状态小组件

时间:2019-12-26 21:22:48

标签: flutter

我根据TextFormField输入在步进器中动态显示Flutter下拉菜单,但是当我尝试选择其中一项时,所选值(_valueDropdownGrade)发生了变化,但始终将默认值保留在UI中,尽管其中包含更新将变量转换为setState()方法。

class _SchoolProfileState extends State<SchoolProfile> {
  int currStep = 0;
  static final FocusNode _nameFocus = FocusNode();
  static final FocusNode _phoneFocus = FocusNode();
  static final FocusNode _emailFocus = FocusNode();
  static final FocusNode _addressFocus = FocusNode();
  static final FocusNode _numberChildFocus = FocusNode();
  static final List<FocusNode> _listChildFocus = [];
  static final FocusNode _ageFocus = FocusNode();
  static SchoolProfileData data = new SchoolProfileData();
  GlobalKey<FormState> _formKey =  GlobalKey<FormState>();
  TextEditingController _controllerNumberKids = TextEditingController();
  TextEditingController _controllerAddressSearch = TextEditingController();
  Timer _throttle;
  String  _valueDropdownGrade = 'MATERNELLE';
  static var childrenFields = new List<Widget>();

  _fieldFocusChange(BuildContext context, FocusNode currentFocus,FocusNode nextFocus) {
    currentFocus.unfocus();
    FocusScope.of(context).requestFocus(nextFocus);
  } 
@override
  void initState() {
     _controllerNumberKids.addListener(onNumberChildChanged);
     _controllerAddressSearch.addListener(onAddressSearchChanged);
    SchedulerBinding.instance.addPostFrameCallback((Duration _) {
      FocusScope.of(context).requestFocus(_nameFocus);
    });
    super.initState();
  }

  void onNumberChildChanged() {
    childrenFields.clear();
    data.childrenNames.clear();
    for (var i = 0; i < int.parse(_controllerNumberKids.text); i++) {
      childrenFields.add(
          new TextFormField(
            textInputAction: TextInputAction.next,
            focusNode: _listChildFocus[i],
            onFieldSubmitted: (term) {
              if (i == _listChildFocus.length - 1) {
                formKeys[currStep].currentState.save();
                if (currStep < getSteps(context).length - 1) {
                  currStep = currStep + 1;
                }
                _fieldFocusChange(context, _listChildFocus[i], _ageFocus);
              }
              else
                _fieldFocusChange(
                    context, _listChildFocus[i], _listChildFocus[i + 1]);
            },
            onSaved: (String value) {
              data.childrenNames.add(value);
            },
            keyboardType: TextInputType.text,
            autocorrect: false,
            decoration: InputDecoration(
                labelText: 'Enter your child name',
                hintText: 'Enter a child name',
                //filled: true,
                icon: const Icon(Icons.person),
                border: InputBorder.none,
                labelStyle: TextStyle(
                    decorationStyle: TextDecorationStyle.solid)),
          )
      );
      childrenFields.add(
          new DropdownButtonHideUnderline(
              child:
              Container(
                  decoration: ShapeDecoration(
                    shape: RoundedRectangleBorder(
                      side: BorderSide(width: 1.0, style: BorderStyle.solid),
                      borderRadius: BorderRadius.all(Radius.circular(10.0)),
                    ),
                  ),
                  child:
                  DropdownButton<String>(
                      icon: Icon(Icons.school),
                      hint: Text('Choose the class'),
                      onChanged: (newValue) {
                        setState(() => _valueDropdownGrade = newValue);
                      },
                      value: _valueDropdownGrade,
                    items:
                        <String>[_valueDropdownGrade,'GRADE 1', 'GRADE 2', 'GRADE 3', 'GRADE 4', 'GRADE 5', 'GRADE 6', 'GRADE 7', 'GRADE 8', 'GRADE 9', 'GRADE 10', 'GRADE 11', 'GRADE 12']
                            .map((String value) {
                      return new DropdownMenuItem<String>(
                  value: value,
                  child: SizedBox(
                    width: 100.0, // for example
                    child: Text(value, textAlign: TextAlign.center),
                  ));
              }).toList()))));
        }
    }

   Step(
          title: const Text('Number of children'),
          // subtitle: const Text('Subtitle'),
          isActive: true,
          state: StepState.indexed,
          content: Form(
            key: formKeys[4],
            child: Column(
              children: <Widget>[
                TextFormField(
                  textInputAction: TextInputAction.next,
                  focusNode: _numberChildFocus,
                  onFieldSubmitted: (term) {
                    formKeys[currStep].currentState.save();
                    if (currStep < getSteps(context).length - 1) {
                      currStep = currStep + 1;
                    }
                    for (var i = 0; i < int.parse(_controllerNumberKids.text); ++i) {
                      _listChildFocus.add(FocusNode());
                    }
                    _fieldFocusChange(context, _numberChildFocus, _listChildFocus[0]);
                  },
                  autocorrect: false,
                  keyboardType: TextInputType.numberWithOptions(
                    decimal: false,
                    signed: true,
                  ),
                  inputFormatters: <TextInputFormatter>[
                    WhitelistingTextInputFormatter.digitsOnly
                  ],
                  controller: _controllerNumberKids,
                  decoration: InputDecoration(
                      labelText: 'Enter number of children',
                      hintText: 'Enter children number',
                      icon: const Icon(Icons.child_care),
                      labelStyle:
                      TextStyle(decorationStyle: TextDecorationStyle.solid)),
                ),
              ],
            ),
          )),
      Step(
          title: const Text('List of Children'),
          // subtitle: const Text('Subtitle'),
          isActive: true,
          state: StepState.indexed,
          content: Form(
              key: formKeys[5],
              child:
                  Column(
                      children: <Widget>[
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: childrenFields.length,
                  itemBuilder: (context, index) {
                      return childrenFields[index];
                  }
              )]
                  ),
          )),

2 个答案:

答案 0 :(得分:0)

您可以在下面复制粘贴运行完整代码
您需要使用StatefulBuilder

代码段

childrenFields.add(
        StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
      return DropdownButtonHideUnderline(
          child: Container(

工作演示

enter image description here

完整代码

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,
      ),
      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 _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SchoolProfile(),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class SchoolProfile extends StatefulWidget {
  @override
  _SchoolProfileState createState() => _SchoolProfileState();
}

class _SchoolProfileState extends State<SchoolProfile> {
  static var childrenFields = new List<Widget>();

  String _valueDropdownGrade;
  List<String> items = [
    'GRADE 1',
    'GRADE 2',
    'GRADE 3',
    'GRADE 4',
    'GRADE 5',
    'GRADE 6',
    'GRADE 7',
    'GRADE 8',
    'GRADE 9',
    'GRADE 10',
    'GRADE 11',
    'GRADE 12'
  ];

  @override
  void initState() {
    _valueDropdownGrade = items[0];
    childrenFields.add(
        StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
      return DropdownButtonHideUnderline(
          child: Container(
              decoration: ShapeDecoration(
                shape: RoundedRectangleBorder(
                  side: BorderSide(width: 1.0, style: BorderStyle.solid),
                  borderRadius: BorderRadius.all(Radius.circular(10.0)),
                ),
              ),
              child: DropdownButton<String>(
                  icon: Icon(Icons.school),
                  hint: Text('Choose the class'),
                  onChanged: (newValue) {
                    setState(() => _valueDropdownGrade = newValue);
                  },
                  value: _valueDropdownGrade,
                  items: items.map((String value) {
                    return new DropdownMenuItem<String>(
                        value: value,
                        child: SizedBox(
                          width: 100.0, // for example
                          child: Text(value, textAlign: TextAlign.center),
                        ));
                  }).toList())));
    }));

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Stepper(steps: [
      Step(
        title: Text("Start"),
        content: Form(
          child: Column(children: <Widget>[
            ListView.builder(
                shrinkWrap: true,
                itemCount: childrenFields.length,
                itemBuilder: (context, index) {
                  return childrenFields[index];
                })
          ]),
        ),
      )
    ]));
  }
}

答案 1 :(得分:0)

在dropDownList内删除 _valueDropdownGrade 并将“ MATERNELLE ”直接放在dropDown列表内。

 String  _valueDropdownGrade = 'MATERNELLE';

 DropdownButton<String>(
                      icon: Icon(Icons.school),
                      hint: Text('Choose the class'),
                      onChanged: (newValue) {
                        setState(() => _valueDropdownGrade = newValue);
                      },
                      value: _valueDropdownGrade,
                    items:
                        <String>['MATERNELLE','GRADE 1', 'GRADE 2', 'GRADE 3', 'GRADE 4', 'GRADE 5', 'GRADE 6', 'GRADE 7', 'GRADE 8', 'GRADE 9', 'GRADE 10', 'GRADE 11', 'GRADE 12']
                            .map((String value) {
                      return new DropdownMenuItem<String>(
                  value: value,
                  child: SizedBox(
                    width: 100.0, // for example
                    child: Text(value, textAlign: TextAlign.center),
                  ));
              }).toList()))));