代码之家  ›  专栏  ›  技术社区  ›  Sdlion

如何实现scafold.of()包装的“高效方式”

  •  1
  • Sdlion  · 技术社区  · 8 年前

    将snackbar显示为操作的输出需要为scafold.of()创建子上下文,如scaffold的手册中所述 of method .

    但我找不到一个更“有效方法”的例子。

    一个更有效的解决方案是将构建函数拆分为多个 小部件。这将引入一个新的上下文,从中可以获取 脚手架。在这个解决方案中,您将拥有一个 创建由新内部小部件的实例填充的脚手架, 然后在这些内部小部件中,您将使用scaffold.of。

    我想使用这个方法,因为所有的递归缩进都是很难读取的。我已经尝试用函数创建表单的提交按钮,甚至尝试扩展raisedbutton类(所以 Scaffold.of 将在一个新的实例化小部件内调用,如文档中所述),但没有任何效果。

    只有我用另一个才有效 Builder 在主管道内 Scaffold 我的应用程序。

    这个工作

    class MyForm extends StatefulWidget {
      Login({Key key, this.title}) : super(key: key);
      final String title;
    
      @override
      _MyFormState createState() => new _MyFormState();
    }
    
    class _MyFormState extends State<MyForm> {
      @override
      Widget build(BuildContext context) {
        final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
        return new Scaffold(
          body: new Builder(
            builder: (BuildContext context) {
              return new ListView(
                children: <Widget>[
                  myForm(context, _formKey),
                ],
              );
            },
          ),
        );
      }
    }
    
    class SubmitButton extends RaisedButton {
      SubmitButton({
        Key key,
        this.onPressed,
        this.child,
      }) : super(key: key, onPressed: onPressed, child: child);
      final VoidCallback onPressed;
      final Widget child;
    
      @override
      Widget build(BuildContext context) {
        return super.build(context);
      }
    }
    
    Widget myForm(
      BuildContext context,
      GlobalKey<FormState> _formKey) => new Container(
      child: new Form(
        key: _formKey,
        child: new Column(
          children: <Widget>[
            new TextFormField(
              validator: (value) {
                if (value.isEmpty) {
                  return 'Write Something';
                }
              },
            ),
            new SubmitButton(
              onPressed: () {
                if (_formKey.currentState.validate()) {
                  Scaffold.of(context).showSnackBar(
                      new SnackBar(content: new Text('Processing'))
                  );
                }
              },
              child: new Text('Submit'),
            ),
          ],
        ),
      ),
    );
    

    我如何移除 建设者 简化它? 我还试图进一步扩展 RaisedButton build() 方法,但陷入依赖关系/类型混乱。我找不到这样的例子。

    2 回复  |  直到 8 年前
        1
  •  1
  •   Richard Heap    8 年前

    一个简单的方法 split your build function into several widgets 只是在一个小部件的构建函数中创建脚手架,在另一个小部件的构建函数中创建按钮。(顺便说一下, myForm 代码中的函数没有任何效果,因为它是作为同一生成函数的一部分运行的,因此上下文的值是相同的。)我重构了代码以引入一个构建脚手架的MyPage小部件,并将其余的部分留在MyForm小部件中。但是,我们现在有两种不同的构建方法:一种构建脚手架,另一种构建需要访问脚手架的表单和按钮。

    class MyPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          body: new MyForm(),
        );
      }
    }
    
    class MyForm extends StatefulWidget {
      @override
      _MyFormState createState() => new _MyFormState();
    }
    
    class _MyFormState extends State<MyForm> {
      final _formKey = new GlobalKey<FormState>();
    
      @override
      Widget build(BuildContext context) {
        return new ListView(
          children: <Widget>[
            new Container(
              child: new Form(
                key: _formKey,
                child: new Column(
                  children: <Widget>[
                    new TextFormField(
                      validator: (value) =>
                          (value.isEmpty) ? 'write something' : null,
                    ),
                    new RaisedButton(
                      onPressed: () {
                        if (_formKey.currentState.validate()) {
                          Scaffold.of(context).showSnackBar(new SnackBar(
                                content: new Text('Processing'),
                              ));
                        }
                      },
                      child: new Text('Submit'),
                    ),
                  ],
                ),
              ),
            ),
          ],
        );
      }
    }
    
        2
  •  2
  •   Mohith7548    8 年前

    是的,如果我们返回一个scaffold,那么这个上下文就不能帮助得到一个snackbar。通过使用globalkey,我们可以做到这一点。请参见下面的代码。

    class ExampleWidget extends StatefulWidget {
      @override
      _ExampleWidgetState createState() => new _ExampleWidgetState();
    }
    
    class _ExampleWidgetState extends State<ExampleWidget> {
      GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState();
    
      _showSnackBar() {
        _scaffoldKey.currentState.showSnackBar(
        new SnackBar(
          content: new Text('You have clicked the button'),
          duration: new Duration(seconds: 4),
        ),
       );
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          key: _scaffoldKey,
          body: new Center(
            child: new RaisedButton(
              onPressed: _showSnackBar(),
              child: new Text('Click Me!'),
            ),
          ),
        );
      }
    }