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

Controlling state of a widget from another widget

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

浮动动作按钮动画由bool clickedCenterFAB控制 在我的代码中,动画容器内的小部件在 class 中定义,我希望在用户编写文本并按下按钮后,动画容器折叠,所以逻辑上我想调用 setState 并分配 clickedCenterFAB =错误的。 我是 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 显然是我创建的一个小部件 class 以避免冗余,并且在我传递到这里的函数的参数中

您不能直接从 UploadPage 调用 setState 的原因是因为 setState 是一个 class 方法,所以它总是只与直接封闭的 class 实例的状态相关联。如果你想改变 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 可以帮助将结构强加到您的项目中并使其更容易推理,尽管您会通常需要编写更多代码才能完成相同的任务。