从另一个小部件控制小部件的状态

问题描述

我正在使用此链接中的示例: https://medium.com/@jb.padamchopra/implementing-a-bottom-app-bar-with-floating-action-button-flutter-463560e1324 Widget from the link

浮动动作按钮动画由bool clickedCenterFAB控制 在我的代码中,动画容器内的小部件在一个类中定义,我希望在用户编写文本并按下按钮后,动画容器折叠,所以从逻辑上讲,我想调用 setState 并分配 clickedCenterFAB = false。 我是 Flutter 的新手,我尝试在 uploadPage 小部件中调用 setState 并尝试更改 clickedCenterFAB 但它没有用。知道怎么做吗?我在这里先向您的帮助表示感谢。 My widget

AnimatedContainer(
              duration: Duration(milliseconds: 300),//if clickedCentreFAB == true,the first parameter is used. If it's false,the second.
              height: clickedCentreFAB
                  ? MediaQuery.of(context).size.height
                  : 10.0,width: clickedCentreFAB
                  ? MediaQuery.of(context).size.height
                  : 10.0,decoration: Boxdecoration(
                borderRadius:
                    BorderRadius.circular(clickedCentreFAB ? 0.0 : 300.0),color: Colors.blue,),child: clickedCentreFAB ? UploadPage() : null)

编辑:遵循迈克尔的解决方案并跟上评论后,这就是我得到的地方

class UploadPage extends StatefulWidget {
  final Function collapseContainer;
  UploadPage(this.collapseContainer);
  @override
  _UploadPageState createState() => 
_UploadPageState(collapseContainer);
}

class _UploadPageState extends State<UploadPage> {
  final Function collapseContainer;
  _UploadPageState(this.collapseContainer);
...
...
CustomButton(
              () {
                if (_controller.text.trim().isNotEmpty) {
                  DatabaseServices().uploadPost(
                      FirebaseAuth.instance.currentUser.uid,_controller.text,!_isChecked);
                  collapseContainer;
                }
              },'Post',Colors.white,

CustomButton 显然是一个小部件类,我创建它是为了避免冗余,并且在我在这里传递的函数中的参数中

解决方法

不能直接从 UploadPage 调用 setState 的原因是因为 setState 是一个类方法,所以它总是只与直接封闭的类实例的状态相关联。如果你想改变 Widget 树中较高的 Widget 的状态,标准的方法是将回调传递给子组件。

在您的情况下,您可以向 UploadPage 小部件添加一个新属性 - 类似于 onButtonPressed:

class UploadPage extends StatelessWidget {
  final Function onButtonPressed;
  UploadPage({required this.onButtonPressed});

  @override
  Widget build(BuildContext context) {
    return YourWidget(
      // ...
      child: RaisedButton(onPressed: onButtonPressed),// ...
    );
  }
}

那么:

AnimatedContainer(
  // ...
  child: clickedCentreFAB 
           ? UploadPage(
             onButtonPressed: () {
               setState(() { return clickedCentreFAB = false; });
             },) 
           : null,)
)

顺便说一句,在某些时候,您的应用程序的状态可能足够复杂,需要使用 blocredux 等解决方案 - 但是,对于这种特定情况,这些可能有点过头了。

如果您发现自己必须通过小部件树的多个级别传递回调和属性,那么 provider 会非常有用。

如果操作、状态和视图之间的映射变得非常复杂,那么 blocredux 可以帮助将结构强加到您的项目中并使其更易于推理,尽管您经常需要编写更多代码来完成相同的任务。