【问题标题】:Flutter: Update state of sibling widgetFlutter:更新兄弟小部件的状态
【发布时间】:2018-05-27 16:15:23
【问题描述】:

如何在 Flutter 中更新兄弟部件的状态?

例如,如果我有一个矩形小部件,我可以通过调用 setState() 并更改颜色变量来从小部件内更改它的颜色(就像下面的“变成绿色”按钮所做的那样)。但是,假设我想要一个矩形之外的按钮来改变它的颜色。我如何向 Rectangle 传达是时候改变它的颜色了,以及要改变什么颜色?

这是我的示例代码。当用户按下“变成蓝色”按钮时,我希望矩形变成蓝色,但我无法从同级小部件访问其状态。

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Hello Rectangle',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Hello Rectangle'),
        ),
        body: Column(
          children: <Widget>[
            HelloRectangle(),
            FlatButton(
            child: Text('Turn Blue!',
              style: TextStyle(fontSize: 40.0),
              textAlign: TextAlign.center,
            ),
            onPressed: () {
              // How to update state of the Rectangle from here?
            },
          ),
          ]
        ),
      ),
    ),
  );
}

class HelloRectangle extends StatefulWidget {
  @override
  HelloRectangleState createState() {
    return new HelloRectangleState();
  }
}

class HelloRectangleState extends State<HelloRectangle> {
  Color _color;

  @override
    void initState() {
      super.initState();
      _color = Colors.red;
    }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: _color,
        height: 400.0,
        width: 300.0,
        child: Center(
          child: FlatButton(
            child: Text('Turn Green!',
              style: TextStyle(fontSize: 40.0),
              textAlign: TextAlign.center,
            ),
            onPressed: () {
              // I can update the state from here because I'm inside the widget
              setState(() {
               _color = Colors.green;
              });
             },
          ),
        ),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter


    【解决方案1】:

    经验法则是,您无法访问层次结构中不在您上方的任何 Widget 的状态。所以,基本上我们需要将状态(颜色)向上移动到祖先。引入一个 StatefulWidget 来构建 Scaffold 或 Column 并将矩形颜色存储在那里。现在矩形小部件不再需要存储颜色,因此可以成为无状态小部件 - 您可以通过构造函数将颜色传入。两个 onPressed 回调现在都可以调用新 StatefulWidget 上的方法,该方法调用 setState。 (除其他方式外,您还可以将该方法传递给矩形小部件。)

    有两个很好的最佳实践介绍herehere

    【讨论】:

    • Tree 打败了我,但你可以看到我们提出了同样的事情。 Tree 还可以使 HelloRectangle 成为 StatelessWidget。每当祖先状态发生变化时(使用新颜色),这个 Widget 就会被重建。有机会时请观看这两个视频,因为它们将帮助您解决最近的其他问题。
    【解决方案2】:

    以下是如何从外部执行此操作的基本示例。

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(
        new MyApp(),
      );
    }
    
    class MyApp extends StatefulWidget {
      const MyApp({
        Key key,
      }) : super(key: key);
    
      @override
      MyAppState createState() {
        return new MyAppState();
      }
    }
    
    class MyAppState extends State<MyApp> {
      MaterialColor _color = Colors.green;
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Hello Rectangle',
          home: Scaffold(
            appBar: AppBar(
              title: Text('Hello Rectangle'),
            ),
            body: Column(children: <Widget>[
              HelloRectangle(_color),
              FlatButton(
                child: Text(
                  _color == Colors.green ? "Turn Blue" : "Turn Green",
                  style: TextStyle(fontSize: 40.0),
                  textAlign: TextAlign.center,
                ),
                onPressed: () {
                  setState(() {
                    _color = _color == Colors.green ? Colors.blue : Colors.green;
                  });
                },
              ),
            ]),
          ),
        );
      }
    }
    
    class HelloRectangle extends StatefulWidget {
      final Color color;
    
      HelloRectangle(this.color);
    
      @override
      HelloRectangleState createState() {
        return new HelloRectangleState();
      }
    }
    
    class HelloRectangleState extends State<HelloRectangle> {
      HelloRectangleState();
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Container(
            color: widget.color,
            height: 400.0,
            width: 300.0,
          ),
        );
      }
    }
    

    【讨论】:

    • 感谢您的代码。这有助于理解,但我接受了 Richard 的回答,因为它包括将状态提升到祖先的解释(就像您在代码中所做的那样)。
    猜你喜欢
    • 2019-08-27
    • 2018-09-01
    • 1970-01-01
    • 2020-10-20
    • 2022-01-21
    • 1970-01-01
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多