【问题标题】:Managing/Handling multiple widgets管理/处理多个小部件
【发布时间】:2019-06-17 22:18:49
【问题描述】:

我提前为我的英语道歉。

我目前正在开发一款移动应用,这是一款简单的游戏。游戏类似于 SimonSays。在我的应用程序中,有 4 个彩色 Container。容器随机突出显示,玩家必须点击突出显示的容器。每个Container 都与一个GestureDetector 相关联。此集合的期望行为是一次只能点击一个(通过更改容器的颜色来显示点击)。问题是我无法弄清楚如何管理容器。 我目前的做法是:

利用Notification 类并通知其他容器(或父小部件)容器已被点击。

我研究了这个主题,但找不到如何使用 Notification 类的好例子。下面提供了当前状态的代码sn-p:

class _parentColorWidget extends State<colorWidget> {
  bool tapped = false;
  Color _initColor;
  Color color;
  _parentColorWidget(Color color) {
    this.color = color;
    this._initColor = color;
  }

  void onTap(bool tapped) {
    setState(() {
      if (tapped) {
        color = Colors.white70;
      } else {
        color = _initColor;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      child: _colorWidget(
        onChanged: onTap,
        context: context,
      ),
    );
  }
}

class colorWidget extends StatefulWidget {
  Color color;
  colorWidget(Color color) {
    this.color = color;
  }
  _parentColorWidget createState() => _parentColorWidget(color);
}

class _colorWidget extends StatelessWidget {

  _colorWidget({@required this.onChanged, this.color, this.context});
  final ValueChanged<bool> onChanged;
  BuildContext context;
  Color color;
  bool tapped = false;

  void _onTap() {
    CustomNotification(current_widget: this).dispatch(context);
    onChanged(!tapped);
  }

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
        onTap: _onTap,
        child: new Container(
          color: color,
        ));
  }
}

我从这段代码生成了四个小部件。通过父小部件进行管理源自我在官方 Flutter 文档中找到的示例。

如果点击了正确的container,我如何使用通知来识别哪个container widget 被点击或更准确?

提前感谢所有答案。

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    如果使用Notification,那么您将一些标识符,例如color 值发送给父级。如果你传递回调,那么这个信息可以在回调中编码,例如:

    class _ParentState extends State<Parent> {
       String selectedColor;
    
       Widget build() {
          return Stack(children: ['Red', 'Green', 'Blue'].map((final color) =>
              Child(
                color: color,
                tapped: selectedColor == color,
                onTap: () { 
                  setState(() {
                     selectedColor = color;
                  })
                }
              )
          ]).toList());
       }
    }
    

    使用这种技术不可能同时选择 2 种颜色,因为所选颜色仅在 selectedColor 中进行跟踪,而其他所有颜色都根据其值重新计算。

    而且我建议坚持使用 1 种方式将调用传递给父小部件,因此可以通过回调或通知,而不是在单个回调中同时使用:

      void _onTap() {
        CustomNotification(current_widget: this).dispatch(context);
        onChanged(!tapped);
      }
    

    对于你正在做的事情,我认为回调应该足以实现一切。

    一些使代码更好的提示:

    1. 遵循命名约定,类名应为大写

    2. 不要传递不必要的信息。在您的代码onChanged(!tapped) 中,这里!tapped 是不必要的,因为这个值是从父级传递下来的。因此,当您在父小部件中传递此值时,您将有 2 个来源获得相同的信息。避免从多个地方访问相同的信息 - 这只会更容易引入与状态相关的错误。

    3. class colorWidget extends StatefulWidget {我看不出这个小部件有任何理由是有状态的。避免拥有过多的状态小部件 - 最好拥有一个具有集中游戏状态和逻辑的状态控制器,然后将信息传递给无状态小部件。尤其要避免有 2 个或更多需要在它们之间具有同步状态的状态小部件。单条信息应该只有一个有状态的小部件来跟踪和控制它。

    【讨论】:

    • 非常感谢,花了我一段时间,但一个非常聪明和顺利的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多