【问题标题】:Controlling state of a widget from another widget从另一个小部件控制小部件的状态
【发布时间】:2021-09-11 20:50:29
【问题描述】:

我正在使用此链接中的示例: 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)

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

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 显然是我为避免冗余而创建的一个小部件类,并且在我在这里传递的函数中的参数中

【问题讨论】:

  • 使用状态管理库,如flutter_blocprovidergetXmobX

标签: flutter dart widget


【解决方案1】:

不能直接从 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 可以帮助您将结构强加到您的项目中并使其更易于推理,尽管您通常需要编写更多代码完成相同的任务。

【讨论】:

  • 感谢您抽出宝贵时间回复!这很好用,但是在我的按钮的 onPressed 中,我正在做很多事情,我正在检查 editTextField 是否为空,如果不是,我正在调用 Firebase 方法将文本上传到 Firestore。并且回调是一个函数,它不适用于所有其他代码,因为它们已经包装在一个函数中。因此,如果我单独使用回调,它会起作用,否则不会。我尝试使用 VoidCallBack 而不是 function 和 MethodCall 但它也不起作用。有什么建议吗?
  • 不!如果我理解正确,您应该仍然可以传递回调 - 或许将其称为“onDone”,然后在其他工作完成后调用它。像onPressed: () async { await doStuff(); onDone(); }, 这样的东西。有什么不可行的原因吗?
  • 我现在试过了,它没有用 :( 文本正在正确上传到 firestore,但之后该功能中的所有内容都不起作用。
  • 啊,太糟糕了 - 您介意分享一下您 UploadPage 中的相关代码,以及 UploadPage 是如何从父窗口小部件构建的吗?
  • 完全没有!给我几个小时,我目前不在我的设置附近
猜你喜欢
  • 2021-07-20
  • 1970-01-01
  • 2019-12-17
  • 2020-11-03
  • 2018-12-04
  • 2020-07-31
  • 1970-01-01
  • 2021-12-26
  • 2021-09-28
相关资源
最近更新 更多