ShowDialog 不改变下拉列表

ShowDialog doesn't change dropdownlist

当我在 dropdownMenuItem 中更改所选项目时,我的对话框不会将其更改为我select编辑的内容。

我有一个下拉列表显示客户端可以 select,当我 select 其中一个 selected 项目没有显示在字段中时,提示保持那里。

它以“SERVIÇO:”开头,并在更改项目后保持原样。 变量获取值但在显示中没有变化。

  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);
          }
        },
      ),
    ]),
  ),
);

}

obraServicoDropDown 在哪里初始化?我怀疑 obraServicoDropDown 的初始化发生在 Stateful Widget 的 Widget 的 build 函数中。因此,即使在 setState 将其更改为正确的状态后,obraServicoDropDown 的重新初始化也会带回原始状态。

从 showDialog 调用 setState 会改变 widget 的状态,但它不会重建对话框,因为 Flutter 不会仅仅因为我们改变了调用对话框的 widget 的状态就认为对话框的状态会改变.

解决这个问题的方法是让对话框有状态;通过 StatefulBuilder 或作为 StatefulWidget。无论哪种情况,现在更改对话框中的下拉状态只会在对话框中更改它;所以我们还需要来自主小部件的回调来更改那里的状态。下面的演示片段。

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(),
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}