Вызов SnackBar из AlertDialog - PullRequest
       17

Вызов SnackBar из AlertDialog

0 голосов
/ 08 апреля 2020

Когда пользователь нажимает кнопку «Удалить» для сотрудника, должен появиться AlertDialog, чтобы предупредить пользователя.

enter image description here

Если пользователь подтверждает удаление затем AlertDialog исчезает, и в нижней части скаффолда должна появиться SnackBar с функцией отмены.

Проблема:

Когда я реализую метод SnackBar showSnackBar (context, index, employee) в классе AlertDialog Я получаю следующую ошибку:

он выбросил следующее утверждение при обработке жеста:

Scaffold.of ( ) вызывается с контекстом, который не содержит Scaffold.

showDeleteDialog(BuildContext context, Employee employee, int index) {
    showDialog(
        context: context,
        builder: (context) => AlertDialog(
              title:
                  Text('Are you sure you want to delete: ${employee.name} ?'),
              actions: <Widget>[
                Row(
                  children: <Widget>[
                    FlatButton(
                        child: Text('Yes'),
                        onPressed: () {
                          DatabaseProvider.db.deleteEmployee(employee.id).then(
                              (_) => BlocProvider.of<EmployeeBloc>(context)
                                  .add(DeleteEmployee(index)));
                          Navigator.pop(context,employee);
                          showSnackBar(context, index, employee);
                        }),
                    FlatButton(
                        child: Text('No!'),
                        onPressed: () => Navigator.pop(context)),
                  ],
                )
              ],
            ));
  }

Вместо этого я подумал, что смогу вернуть сотрудника из showDeleteDialog, когда подтвердлю удаление. Когда результат не нулевой, тогда я должен показать SnackBar. Я пытался реализовать это с помощью Future / Asyn c, но безуспешно.

onPressed: () async {
                        Employee deletedEmployee = await showDeleteDialog(context, employee, index);
                        await showSnackBar(context, index, deletedEmployee);
                    },

Редактировать: Я хотел бы по возможности избегать использования GlobalKey , так как я прочитал, это не очень хорошо для производительности приложения.

Ответы [ 2 ]

0 голосов
/ 08 апреля 2020

Нашли решение, и это очень просто ...

Мне нужно было только переименовать один из контекста в dialogContext

showDeleteDialog(BuildContext context, Employee employee, int index) {
    showDialog(
        context: context,
        builder: (dialogContext) => AlertDialog(
              title:
                  Text('Are you sure you want to delete: ${employee.name} ?'),
              actions: <Widget>[
                Row(
                  children: <Widget>[
                    FlatButton(
                        child: Text('Yes'),
                        onPressed: () {
                          DatabaseProvider.db.deleteEmployee(employee.id).then(
                              (_) => BlocProvider.of<EmployeeBloc>(dialogContext)
                                  .add(DeleteEmployee(index)));
                          Navigator.pop(dialogContext);
                          showSnackBar(context, index, employee);
                        }),
                    FlatButton(
                        child: Text('No!'),
                        onPressed: () => Navigator.pop(context)),
                  ],
                )
              ],
            ));
  }
0 голосов
/ 08 апреля 2020

Как говорит ошибка Scaffold.of() called with a context that does not contain a Scaffold., это означает, что текущий context, который вы передаете методу showSnackBar(), не содержит Scaffold в непосредственном родителе.

Мы можем исправить это с помощью GlobalKey и присвоить его Scaffold. Объявите global key в своем виджете с состоянием и передайте его как ключ в Scaffold, как показано ниже:

final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

....

return Scaffold(
  key: _scaffoldKey,
  appBar: AppBar(
    title: Text(widget.title),
  ),

Я вызываю метод _showSnackBar() после navigator.pop() при нажатии OK. внутри alertDialog, как показано ниже:

return AlertDialog(
        title: Text('Not in stock'),
        content: const Text('This item is no longer available'),
        actions: <Widget>[
          FlatButton(
            child: Text('Ok'),
            onPressed: () {
              Navigator.of(context).pop();
              _showSnackBar();
            }, 
          ),
        ],
      );

Затем в методе _showSnackBar() используйте клавишу для отображения панели закусок, как показано ниже:

void _showSnackBar() {
    _scaffoldKey.currentState.showSnackBar(
  SnackBar(
    content: Text('Snackbar is displayed'),
  ));    

  }

При таком подходе как только вы нажмете кнопку OK на alertDialog, диалоговое окно закроется, и вы увидите снэк-бар. Возможно, вам придется настроить его в соответствии с вашим кодом, как вы указали выше.

Надеюсь, что это ответит на ваш вопрос и решит вашу проблему.

...