从 AlertDialog 中调用 SnackBar
Call SnackBar from within an AlertDialog
当用户点击删除某个员工时,会弹出一个AlertDialog来警告用户。
如果用户确认删除,AlertDialog 就会消失,在 Scaffold 的底部应该会出现一个带有撤消功能的 SnackBar。
问题:
当我在 AlertDialog class 中实现 SnackBar 方法 showSnackBar(context, index, employee) 时,出现以下错误:
he following assertion was thrown while handling a gesture:
Scaffold.of() called with a context that does not contain a 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)),
],
)
],
));
}
相反,当我确认删除时,我认为我可以 return 来自 showDeleteDialog 的员工。当结果不为空时,我应该显示 SnackBar。我尝试用 Future/Async 来实现它,但没有成功。
onPressed: () async {
Employee deletedEmployee = await showDeleteDialog(context, employee, index);
await showSnackBar(context, index, deletedEmployee);
},
编辑: 我想尽可能避免使用 GlobalKey,因为我读到它不利于应用程序的性能。
如错误所述 Scaffold.of() called with a context that does not contain a Scaffold.
,这意味着您传递给 showSnackBar()
方法的当前 context
在直接父级中不包含 Scaffold
。
我们可以使用 GlobalKey
解决这个问题,并将其分配给 Scaffold
。在您的有状态小部件中声明一个 global key
并将其作为键传递到您的 Scaffold
中,如下所示:
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
....
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text(widget.title),
),
我在 alertDialog
内点击 navigator.pop()
按钮后调用方法 _showSnackBar()
,如下所示:
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()
方法中,使用按键显示snackbar,如下:
void _showSnackBar() {
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: Text('Snackbar is displayed'),
));
}
使用这种方法,一旦您点击 alertDialog
上的 OK
按钮,对话框就会关闭,您会看到快餐栏。您可能需要根据您在上面分享的代码对其进行自定义。
希望这能回答您的问题并解决您的问题。
找到解决方案,而且非常简单...
我只需要将其中一个 context 重命名为 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)),
],
)
],
));
}
当用户点击删除某个员工时,会弹出一个AlertDialog来警告用户。
如果用户确认删除,AlertDialog 就会消失,在 Scaffold 的底部应该会出现一个带有撤消功能的 SnackBar。
问题:
当我在 AlertDialog class 中实现 SnackBar 方法 showSnackBar(context, index, employee) 时,出现以下错误:
he following assertion was thrown while handling a gesture:
Scaffold.of() called with a context that does not contain a 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)),
],
)
],
));
}
相反,当我确认删除时,我认为我可以 return 来自 showDeleteDialog 的员工。当结果不为空时,我应该显示 SnackBar。我尝试用 Future/Async 来实现它,但没有成功。
onPressed: () async {
Employee deletedEmployee = await showDeleteDialog(context, employee, index);
await showSnackBar(context, index, deletedEmployee);
},
编辑: 我想尽可能避免使用 GlobalKey,因为我读到它不利于应用程序的性能。
如错误所述 Scaffold.of() called with a context that does not contain a Scaffold.
,这意味着您传递给 showSnackBar()
方法的当前 context
在直接父级中不包含 Scaffold
。
我们可以使用 GlobalKey
解决这个问题,并将其分配给 Scaffold
。在您的有状态小部件中声明一个 global key
并将其作为键传递到您的 Scaffold
中,如下所示:
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
....
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text(widget.title),
),
我在 alertDialog
内点击 navigator.pop()
按钮后调用方法 _showSnackBar()
,如下所示:
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()
方法中,使用按键显示snackbar,如下:
void _showSnackBar() {
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: Text('Snackbar is displayed'),
));
}
使用这种方法,一旦您点击 alertDialog
上的 OK
按钮,对话框就会关闭,您会看到快餐栏。您可能需要根据您在上面分享的代码对其进行自定义。
希望这能回答您的问题并解决您的问题。
找到解决方案,而且非常简单...
我只需要将其中一个 context 重命名为 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)),
],
)
],
));
}