简体   繁体   中英

ShowDialog doesn't change dropdownlist

When I change the chosen item in dropdownMenuItem, my dialog doesn't change it to what I selected.

I have a dropdown that shows what the client can select, when I select one of them the selected item doesn't display in the field, the hint keeps there.

it starts with "SERVIÇO:" and keeps like that after changing the item. the variable gets the value but it doesn't change in display.

  Future<void> _addObraServico(BuildContext context) async {
return showDialog(
  context: context,
  child: new Dialog(
    backgroundColor: blueSoftwar,
    child: new Column(children: <Widget>[
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: Container(
          child: Text(
            "SERVIÇOS",
            style: TextStyle(
              fontSize: 20,
              color: Colors.white,
            ),
          ),
        ),
      ),
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: new Theme(
          data: Theme.of(context).copyWith(
            canvasColor: orangeSoftwar,
          ),
          child: Container(
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
              borderRadius: BorderRadius.all(Radius.circular(
                      5.0) //                 <--- border radius here
                  ),
            ),
            child: DropdownButton<String>(
              isExpanded: true,
              value: obraServicoDropDown,
              icon: const Icon(
                Icons.arrow_downward,
                color: Colors.white,
              ),
              style: const TextStyle(color: Colors.white),
              underline: SizedBox(),
              onChanged: (String newValue) {
                setState(() {
                  obraServicoDropDown = newValue;
                  print(obraServicoDropDown);
                });
              },
              items: <String>['', 'SERVICO1', 'SERVICO2', 'SERVICO3']
                  .map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(
                    value,
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 20,
                    ),
                  ),
                );
              }).toList(),
              hint: Container(
                child: Text(
                  " SERVIÇO:",
                  style: TextStyle(color: Colors.white, fontSize: 20),
                  textAlign: TextAlign.end,
                ),
              ),
            ),
          ),
        ),
      ),
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: new TextField(
          style: TextStyle(color: Colors.white, fontSize: 20),
          decoration: new InputDecoration(
            focusedBorder: OutlineInputBorder(
              borderRadius: BorderRadius.all(Radius.circular(5.0)),
              borderSide: BorderSide(color: Colors.white),
            ),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.all(Radius.circular(5.0)),
              borderSide: BorderSide(color: Colors.white),
            ),
            hintText: "Descrição *",
            hintStyle: TextStyle(fontSize: 20.0, color: Colors.white),
          ),
          controller: _tDescricaoObra,
        ),
      ),
      if (showAlert)
        Text(
          "Preencha os campos",
          style: TextStyle(fontSize: 20, color: Colors.red),
        ),
      new FlatButton(
        color: Colors.orange,
        child: new Text(
          "CADASTRAR",
          style: TextStyle(color: Colors.white),
        ),
        onPressed: () {
          if (obraServicoDropDown == null || _tDescricaoObra.text.isEmpty) {
            showAlert = true;
          } else {
            ServicoObra servico = new ServicoObra();
            servico.servico = obraServicoDropDown;
            servico.descricao = _tDescricaoObra.text;
            setState(() {
              servicos.add(servico);
            });
            obraServicoDropDown = null;
            _tDescricaoObra.clear();
            showAlert = false;
            Navigator.pop(context);
          }
        },
      ),
    ]),
  ),
);

}

Calling setState from showDialog changes the state of the widget, but it does not rebuild the dialog, because Flutter does not consider the state of the dialog to be changed just because we changed the state of the widget that called the dialog.

对话框下拉菜单 - 问题

The way to fix this is to make the dialog stateful; either through StatefulBuilder or as a StatefulWidget. In either case, now changing the dropdown state in the dialog will only change it in the dialog; so we also need a callback from the main widget to change the state there as well. Demo snippet below.

在此处输入图像描述

class DialogDropdown extends StatefulWidget {
  const DialogDropdown({Key? key}) : super(key: key);

  @override
  State<DialogDropdown> createState() => _DialogDropdownState();
}

class _DialogDropdownState extends State<DialogDropdown> {
  String? _grade;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text("Dialog Dropdown"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              _grade ?? "Unknown",
              style: Theme.of(context).textTheme.headline4,
            ),
            const Text(
              'Grade',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          showDialog(
            context: context,
            builder: (context) => gradeDialog(),
          );
        },
        tooltip: 'Change Grade',
        child: const Icon(Icons.arrow_upward),
      ),
    );
  }

  void _changeGrade(_newGrade) {
    setState(
      () {
        _grade = _newGrade;
      },
    );
  }

  StatefulBuilder gradeDialog() {
    return StatefulBuilder(
      builder: (context, _setter) {
        return Dialog(
          child: Padding(
            padding: const EdgeInsets.all(15),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(_grade ?? "Unknown"),
                const SizedBox(height: 30),
                DropdownButton<String>(
                  value: _grade,
                  onChanged: (String? _newGrade) {
                    _setter(
                      () {
                        _grade = _newGrade!;
                      },
                    );
                    _changeGrade(_newGrade);
                  },
                  items: ["A", "B"].map<DropdownMenuItem<String>>(
                    (String value) {
                      return DropdownMenuItem<String>(
                        value: value,
                        child: Text(value),
                      );
                    },
                  ).toList(),
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

Where is obraServicoDropDown being initialized? I suspect that the initialization of obraServicoDropDown is happening within the Widget's build function of the Stateful Widget. Hence, even after setState changes it to the correct state, the re-initialization of obraServicoDropDown brings back the original state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM