如何实现 "efficient way" of Scafold.of() 换行

How to implement the "efficient way" of Scafold.of() wrapping

如 Scaffold 的 of method.

手册所述,将快餐栏显示为操作的输出需要为 Scafold.of() 创建子上下文

但是我在此处找不到更多 "efficient method" 描述的示例。

A more efficient solution is to split your build function into several widgets. This introduces a new context from which you can obtain the Scaffold. In this solution, you would have an outer widget that creates the Scaffold populated by instances of your new inner widgets, and then in these inner widgets you would use Scaffold.of.

我想使用这种方法,因为所有递归缩进都很难阅读。我已经尝试使用函数创建表单的提交按钮,甚至尝试扩展 RaisedButton class(因此 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() 方法,但陷入了依赖/输入混乱。我找不到这方面的例子。

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

split your build function into several widgets 的一种简单方法是在一个 Widget 的构建函数中创建脚手架,在另一个 Widget 的构建函数中创建按钮。 (顺便说一下,你代码中的 myForm 函数没有效果,因为它是 运行 作为同一个构建函数的一部分,所以 context 的值是相同的。)我重构了你的代码以引入一个 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'),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

How do I remove the Builder and simplify it?

不行。使用构建器是最简单的方法。使用键是更复杂的方法(作为最小值,它增加了更多的代码行。

您只需添加一个构建器层

之前

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

之后

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

还有什么可以更简单?