【问题标题】:Snackbar in SimpleDialog FlutterSimpleDialog Flutter 中的 Snackbar
【发布时间】:2019-07-04 04:21:11
【问题描述】:

在我的 Simpledialog 中将快餐栏添加到按下方法时,我遇到了以下错误代码。 [使用不包含 Scaffold 的上下文调用 Scaffold.of()。]

我想就如何提供正确的上下文来解决问题征求您的意见。

import 'package:flutter/material.dart';



void main() {
  runApp(new MaterialApp(home: new AlertApp()));
}

class AlertApp extends StatefulWidget {
  @override
  _AlertAppState createState() => _AlertAppState();
}

class _AlertAppState extends State<AlertApp> {


  SimpleDialog _simdalog;

  void sDialog(){
    _simdalog = new SimpleDialog(
      title: new Text("Add To Shopping Cart"),
      children: <Widget>[
        new SimpleDialogOption(
          child: new Text("Yes"),
          onPressed: (){
            final snackBar = SnackBar(content: Text('Purchase Successful'));
            Scaffold.of(context).showSnackBar(snackBar);
          },
        ),
        new SimpleDialogOption(
          child: new Text("Close"),
          onPressed:() {Navigator.pop(context);},
        ),
      ],
    );
    showDialog(context: context, builder: (BuildContext context){
      return _simdalog;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: new Center(
        child: Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
        new RaisedButton(
            child: new Text("Add to Shopping Cart [Simple]"),
            onPressed:(){
              sDialog();
            }),
          ],
        ),
      ),
    );
  }
}

【问题讨论】:

标签: flutter snackbar simpledialog


【解决方案1】:

您应该在 showDialog 中创建一个 Scaffold 小部件,并创建一个 Builder 小部件作为 Scaffold 的子级,并将上下文作为参数传递。

 void sDialog({BuildContext context}){
     
    _simdalog = new SimpleDialog(
      title: new Text("Add To Shopping Cart"),
      children: <Widget>[
        new SimpleDialogOption(
          child: new Text("Yes"),
          onPressed: (){
            final snackBar = SnackBar(content: Text('Purchase Successful'));
            Scaffold.of(context).showSnackBar(snackBar);
          },
        ),
        new SimpleDialogOption(
          child: new Text("Close"),
          onPressed:() {Navigator.pop(context);},
        ),
      ],
    );
    showDialog(context: context, builder: (BuildContext context){
      return GestureDetector(
          onTap: (){Navigator.of(context).pop();},
          child: Scaffold(
            body: Builder(
                builder: (context){
                    return  _simdalog(context: context);
                }
            ),  
         ),);
    });
  }

【讨论】:

    【解决方案2】:

    您可以从 showDialog 方法返回一个布尔值,并使用它来确定是否显示小吃栏:

    void main() {
      runApp(MaterialApp(
        home: AlertApp(),
      ));
    }
    
    class AlertApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                MyShoppingButton(),
              ],
            ),
          ),
        );
      }
    }
    
    // Separate out the button from _AlertAppState so that the call to
    // showSnackBar comes from a different BuildContext
    class MyShoppingButton extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return RaisedButton(
          child: Text("Add to Shopping Cart [Simple]"),
          // Use an async onPressed method so that we can wait for the
          // result from the dialog before deciding whether to show the snackbar
          onPressed: () async {
            bool result = await showDialog<bool>(
              context: context,
              builder: (BuildContext context) {
                return MyShoppingDialog();
              },
            );
            // Check if result is null below as Flutter will throw Exception if
            // tries determining whether to enter an if branch will a null boolean
            if (result != null && result) {
              final snackBar = SnackBar(content: Text('Purchase Successful'));
              Scaffold.of(context).showSnackBar(snackBar);
            }
          },
        );
      }
    }
    
    class MyShoppingDialog extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return SimpleDialog(
          title: Text("Add To Shopping Cart"),
          children: <Widget>[
            SimpleDialogOption(
              child: Text("Yes"),
              onPressed: () {
                // Pop with a result of true so that MyShoppingButton
                // knows to show snackbar. In any other case
                // (including the user dismissing the dialog), MyShoppingButton
                // null receive null, and so will not show the snackbar
                Navigator.of(context).pop(true);
              },
            ),
            SimpleDialogOption(
              child: Text("Close"),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        );
      }
    }
    
    

    【讨论】:

      【解决方案3】:

      解决方案 1:正如 Mazin Ibrahim 在 cmets Scaffold.of() called with a context that does not contain a Scaffold 中提到的那样

      final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
      ...
      Scaffold(
        key: _scaffoldKey,
      ...
      onPressed: () {
      
                            _scaffoldKey.currentState.showSnackBar(
                                SnackBar(
                                  content: Text('Purchase Successful'),
                                  duration: Duration(seconds: 3),
                                ));
                    }
      

      解决方案 2: 使用包flushbar,您还可以在顶部显示通知
      冲洗条链接:https://github.com/AndreHaueisen/flushbar
      另一个使用flushbar的建议How to show snackbar after navigator.pop(context) in Flutter?

          Flushbar(
            title: "Hey Ninja",
            message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
            flushbarPosition: FlushbarPosition.TOP,
            flushbarStyle: FlushbarStyle.FLOATING,
            reverseAnimationCurve: Curves.decelerate,
            forwardAnimationCurve: Curves.elasticOut,
            backgroundColor: Colors.red,
            boxShadows: [BoxShadow(color: Colors.blue[800], offset: Offset(0.0, 2.0), blurRadius: 3.0)],
            backgroundGradient: LinearGradient(colors: [Colors.blueGrey, Colors.black]),
            isDismissible: false,
            duration: Duration(seconds: 4),
            icon: Icon(
              Icons.check,
              color: Colors.greenAccent,
            ),
            mainButton: FlatButton(
              onPressed: () {},
              child: Text(
                "CLAP",
                style: TextStyle(color: Colors.amber),
              ),
            ),
            showProgressIndicator: true,
            progressIndicatorBackgroundColor: Colors.blueGrey,
            titleText: Text(
              "Hello Hero",
              style: TextStyle(
                  fontWeight: FontWeight.bold, fontSize: 20.0, color: Colors.yellow[600], fontFamily: "ShadowsIntoLightTwo"),
            ),
            messageText: Text(
              "You killed that giant monster in the city. Congratulations!",
              style: TextStyle(fontSize: 18.0, color: Colors.green, fontFamily: "ShadowsIntoLightTwo"),
            ),
          )..show(context);
      

      【讨论】:

      猜你喜欢
      • 2017-11-23
      • 2022-11-11
      • 1970-01-01
      • 2018-09-01
      • 2021-11-29
      • 2017-03-27
      • 1970-01-01
      • 2019-12-15
      • 2020-02-29
      相关资源
      最近更新 更多