Как обновить AlertDialog во флаттере?

В настоящее время у меня есть AlertDialog с IconButton. Пользователь может нажать на иконку, у меня есть два цвета для каждого клика. Проблема в том, что мне нужно закрыть AlertDialog и снова открыть, чтобы увидеть изменение состояния значка цвета. Я хочу немедленно изменить цвет IconButton, когда пользователь щелкнет по нему.

Вот код:

bool pressphone = false;
//....
new IconButton(
   icon: new Icon(Icons.phone),
   color: pressphone ? Colors.grey : Colors.green,
   onPressed: () => setState(() => pressphone = !pressphone),
),

Ответ 1

Это потому, что вам нужно поместить свой AlertDialog в его собственный StatefulWidget и переместить всю логику манипуляции состояниями на цвет там.

Обновление:

enter image description here

void main() => runApp(MaterialApp(home: Home()));

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child: RaisedButton(
      child: Text('Open Dialog'),
      onPressed: () {
        showDialog(
            context: context,
            builder: (_) {
              return MyDialog();
            });
      },
    )));
  }
}

class MyDialog extends StatefulWidget {
  @override
  _MyDialogState createState() => new _MyDialogState();
}

class _MyDialogState extends State<MyDialog> {
  Color _c = Colors.redAccent;
  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      content: Container(
        color: _c,
        height: 20.0,
        width: 20.0,
      ),
      actions: <Widget>[
        FlatButton(
            child: Text('Switch'),
            onPressed: () => setState(() {
                  _c == Colors.redAccent
                      ? _c = Colors.blueAccent
                      : _c = Colors.redAccent;
                }))
      ],
    );
  }
}

Ответ 2

showDialog(
  context: context,
  builder: (context) {
    String contentText = "Content of Dialog";
    return StatefulBuilder(
      builder: (context, setState) {
        return AlertDialog(
          title: Text("Title of Dialog"),
          content: Text(contentText),
          actions: <Widget>[
            FlatButton(
              onPressed: () => Navigator.pop(context),
              child: Text("Cancel"),
            ),
            FlatButton(
              onPressed: () {
                setState(() {
                  contentText = "Changed Content of Dialog";
                });
              },
              child: Text("Change"),
            ),
          ],
        );
      },
    );
  },
);

Ответ 3

В настоящее время для получения значения Dialog я использую

showDialog().then((val){
setState (() {}); 
print (val);
});
Пример

1-й экран

    onPressed: () { 
    showDialog(
       context: context,
       barrierDismissible: false,
       builder: (context) {
         return AddDespesa();
       }).then((val) {
         setState(() {});
         print(val);
        }
    );
   }

2-й экран

AlertDialog(
    title: Text("Sucesso!"),
    content: Text("Gasto resgristrado com sucesso"),
    actions: <Widget>[
    FlatButton(
      child: Text("OK"),
      onPressed: () {
         Navigator.pop(context, true);
      },
     ),
   ],
 );

Будет напечатано верно,

Ответ 4

Документы предполагают, что вы используете StatefulBuilder в разделе content AlertDialog. Даже у StatefulBuilder docs действительно есть пример с диалоговым окном.

Что он делает, так это предоставляет вам новый контекст и функцию setState для восстановления при необходимости.

Пример кода из документации:

showDialog<void>(
  context: context,
  builder: (BuildContext context) {
    int selectedRadio = 0;
    return AlertDialog( 
      content: StatefulBuilder(  // You need this, notice the parameters below:
        builder: (BuildContext context, StateSetter setState) {
          return Column(
            mainAxisSize: MainAxisSize.min,
            children: List<Widget>.generate(4, (int index) {
              return Radio<int>(
                value: index,
                groupValue: selectedRadio,
                onChanged: (int value) {
                  setState(() => selectedRadio = value);
                },
              );
            }),
          );
        },
      ),
    );
  },
);

И, как я уже говорил, об этом говорится в документах showDialog:

[...] Возвращенный компоновщиком виджет не имеет общего контекста с местоположением этот showDialog изначально вызывается из. Используйте StatefulBuilder или пользовательский StatefulWidget, если диалог должен обновляться динамически.