【问题标题】:How to implement the "efficient way" of Scafold.of() wrapping如何实现 Scaffold.of() 包装的“高效方式”
【发布时间】:2018-11-01 19:58:09
【问题描述】:

如 Scaffold 的 of method 手册中所述,将小吃栏显示为操作的输出需要为 Scafold.of() 创建子上下文。

但我找不到此处描述的这种更“有效方法”的示例。

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

我想使用这种方法,因为所有递归缩进都很难阅读。我已经尝试使用函数创建表单的提交按钮,甚至尝试扩展 RaisedButton 类(因此 Scaffold.of 将在文档中指出的新实例化 Widget 中被调用)无济于事。

只有当我在我的应用程序的主 Scaffold 中使用另一个 Builder 时它才有效。

这行得通

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'),
        ),
      ],
    ),
  ),
);

如何删除Builder 并简化它? 我还尝试进一步扩展 RaisedButton build() 方法,但陷入了依赖/打字混乱。我找不到这样的例子。

【问题讨论】:

    标签: flutter scaffold


    【解决方案1】:

    是的,如果我们返回一个 Scaffold ,那么该上下文将无助于获得一个小吃店。通过使用 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!'),
            ),
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

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

      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'),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          );
        }
      }
      

      【讨论】:

      • 然后文本试图说“将您的小部件拆分为不同的构建功能”。在一个小部件构建函数中创建 Scaffold,在另一个小部件构建函数中实例化将调用 Scaffold.of() 的小部件
      • 我不太明白Form() 是多余的。在 Widget 的层次结构中向上移动 Scaffold 后,我试图取消表单,它会抛出一个异常,说 _formKey.currentState.validate() 正在 null 对象上执行
      • 我从您的问题和代码中了解到您试图通过将表单创建提取到一个名为 myForm 的方法中来解决问题。我只是指出这不起作用,因为该方法是从 build 调用的,因此上下文是相同的。答案引入了第二个小部件,因此您现在有 2 种不同的构建方法可以摆脱 Builder。我内联该函数只是为了使答案更清楚。 (如果没有道歉!)
      【解决方案3】:

      如何删除 Builder 并简化它?

      没办法。使用 builder 是最简单的方法。使用键是更复杂的方法(作为 minium,它增加了更多的代码行。

      您只需添加一个构建器层

      之前

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: ...,
        );
      }
      

      之后

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Builder(
            builder: (c) => ...,
          ),
        );
      }
      

      还有什么可以更简单的?

      【讨论】:

        猜你喜欢
        • 2018-12-25
        • 1970-01-01
        • 1970-01-01
        • 2017-03-05
        • 1970-01-01
        • 2013-02-21
        • 2010-11-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多