屏幕 initState 上的 Flutter Snackbar

Flutter Snackbar on screen initState

三个问题:

  1. 如何在 flutter 中的 initState 或应用程序加载初始屏幕时加载 snackbar?我有下面的代码,但它会抛出错误并且不会加载屏幕文本。
class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {

  @override
  void initState() {
    print('In Init State Stream Builder');
  
    _showSnackbar(context);
    
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("Hello World"),
      ),
    );
  }

  void _showSnackbar(BuildContext ctx) {
    Scaffold.of(ctx).showSnackBar(
      SnackBar(
        content: ListTile(
          onTap: () {
            Scaffold.of(ctx).hideCurrentSnackBar();
          },
          subtitle: Text("and i'm a subtitle"),
          trailing: Icon(Icons.check),
        ),
        duration: Duration(
          days: 1,
        ),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
        behavior: SnackBarBehavior.floating,
      ),
    );
  }
}

以上代码加载时报错

这里先回答第一个问题。你这里有两个问题。

  1. 在 Flutter 中,您不能在构建方法中具有 Scaffold 的小部件中调用 Scaffold.of(context)Scaffold.of(context) 必须始终从具有 Scaffold 作为其祖先的上下文中调用。

  2. 如果你想在initState中调用showSnackbar,你必须在延迟函数中调用它。持续时间可以为 0。

我这里有一个简单的例子来展示

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ChildWidget(),
    );
  }
}

class ChildWidget extends StatefulWidget {
  @override
  _ChildWidgetState createState() => _ChildWidgetState();
}

class _ChildWidgetState extends State<ChildWidget> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  @override
  void initState() {
    Future<Null>.delayed(Duration.zero, () {
      _showSnackbar();
    });
    super.initState();
  }

  void _showSnackbar() {
    Scaffold.of(context).showSnackBar(SnackBar(content: Text('content')));
  }
}

要在 initState() 上初始化 Snackbar,要么延迟,要么在构建布局后执行函数,如下所示:

void initState() {
 super.initState();
WidgetsBinding.instance
    .addPostFrameCallback((_) => _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Your message here..")));
}

在 flutter 中 context 仅在构建完成后可用,您可以使用 FutureWidgetsBinding.instance.addPostFrameCallbackSchedulerBinding.instance.addPostFrameCallback.

但我希望如果您像这样将 _showSnackbar(context); 移动到 build 方法,您会得到相同的结果。

  @override
  Widget build(BuildContext context) {
    _showSnackbar(context);
    return Scaffold(
      body: Center(
        child: Text("Hello World"),
      ),
    );
  }

与其将其放入 initState() 中,不如将其放入 didChangeDependencies()

@override
  void didChangeDependencies () {
   print('In Init State Stream Builder');

   _showSnackbar(context);

   super.didChangeDependencies();
  }

这对我有用:)

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      // do what you want here
      final snackBar = SnackBar(
        content: const Text('Yay! A SnackBar!'),
        action: SnackBarAction(
          label: 'Undo',
          onPressed: () {
            // Some code to undo the change.
          },
        ),
      );

      // Find the ScaffoldMessenger in the widget tree
      // and use it to show a SnackBar.
      ScaffoldMessenger.of(context).showSnackBar(snackBar);
    });

  }