简体   繁体   English

Flutter:从单个父窗口小部件控制多个子窗口小部件的状态

[英]Flutter: Controlling the states of multiple child widgets from a single parent widget

I have a Menu Stateful Widget which is a Parent Widget to multiple instances of a MenuIcon child widget which returns a container.我有一个Menu状态小部件,它是返回容器的MenuIcon子小部件的多个实例的父小部件。 The user is able to tap the MenuIcon widgets individually so they highlight when an active bool is true and don't when it is not.用户可以单独点击MenuIcon小部件,以便在active布尔为真时突出显示,而不是在不为真时突出显示。 Right now this is all controlled within the MenuIcon class, which from reading here is not the best approach considering that the state of each of the Icons are going to play an important role in the app, and so I want to be able to manage it within the parent widgets.现在这一切都在MenuIcon class中进行控制,考虑到每个图标的 state 将在应用程序中发挥重要作用,因此我希望能够管理它。在父小部件中。 But I'm not exactly sure how to do this, the tutorial linked earlier has simply one parent widget -> one child widget and so it is very easy to manage the state from the parent widget.但我不确定如何执行此操作,之前链接的教程只有一个父小部件 -> 一个子小部件,因此从父小部件管理 state 非常容易。 But in this case since the parent widget holds multiple instances of the child widgets each with their own active/inactive state I can't think of an easy way to do this.但在这种情况下,由于父小部件拥有多个子小部件实例,每个实例都有自己的活动/非活动 state 我想不出一个简单的方法来做到这一点。

Currently my hierarchy looks like this:目前我的层次结构如下所示: I intend for the MenuIcons to simply manage their own animation, the Menu class to manage the states of each MenuIcon , and the HomePage to hold a list of every MenuIcon that is currently active.我打算让 MenuIcon 简单地管理自己的 animation,让Menu class 管理每个MenuIcon的状态,并让HomePage保存当前处于活动状态的每个MenuIcon的列表。

The code for the Menu and MenuIcon classes are as follows: MenuMenuIcon类的代码如下:

//----------------- Menu ------------------------------------------
//These classes control the scrollable menu that appears when the
//dropdown is pressed

class Menu extends StatefulWidget {
  final String _category;

  Menu(this._category);

  @override
  _MenuState createState() => _MenuState(category: this._category);

}

class _MenuState extends State<Menu> {
  List<Offer> _offersList = createOffers();
  String category;

  _MenuState({@required this.category});

  //build method
  Widget build(BuildContext context) {
    final _menuItems = List<Container>();
    //builds an item widget if the category is correct.
    for (int i = 0; i < _offersList.length; i++) {
      if (this.category == _offersList[i].category) {
        // adds a container containing the MenuIcon object, with the offer
        // in question passed through _offersList[i]
        _menuItems.add(Container(
            child: MenuIcon(
                offer: _offersList[i],
        )));
      }
    }

    //This particular widget tree allows to have a horizontal scrolling
    //menu within a fixed widget
    if (_menuItems.length > 0) {
      return SizedBox(
        child: Row(
          children: [
            Expanded(
                child: ListView(
                  children: _menuItems,
                  scrollDirection: Axis.horizontal,
            )),
          ],
        ),
        height: 154,
     );
   } else {
      return Row(
        children: [
          Container(
            child: Text(
              'Sorry! There are no offers available for this category',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: 14.0,
              ),
            ),
            padding: EdgeInsets.only(left: 12),
          ),
        ],
      );
    }
  }
}

//------------------- MenuIcon class -----------------------------

class MenuIcon extends StatefulWidget {
  Offer offer;

  MenuIcon({@required this.offer});

  @override
  _MenuIconState createState() => _MenuIconState(this.offer);
}

class _MenuIconState extends State<MenuIcon> {
  Offer _offer;
  bool active;

  _MenuIconState(this._offer) {
    this.active = false;
  }

  void _handleTap() {
    setState(() {
      active = !active;
    });
  }

  Widget build(BuildContext context) {
    //print('icon rebuilt with active = $active');
    var label = _offer.discount.toString();
    return Container(
      child: GestureDetector(
        child: Column(
          children: [
            _offer.image,
            Text(
               '$label% off',
               style: TextStyle(
                  color: Colors.red,
                  fontSize: 14.0,
               ),
            ),
          ],
          mainAxisAlignment: MainAxisAlignment.center,
        ),
        onTap: _handleTap,
      ),
      //changes the colour if the icon is selected or not
      color: active ? Colors.yellow : Colors.white,
    );
  }
}

Another viable option is the Async_Redux package available on pub.dev另一个可行的选项是 pub.dev 上提供的 Async_Redux package

It has way less boilerplate code and allows very easy state implementation.它的样板代码更少,并且可以非常轻松地实现 state。 You can configure ReduxActions to manipulate state from your actions.您可以配置 ReduxActions 以从您的操作中操作 state。 The whole app reacts to the state manipulations.整个应用程序对 state 操作做出反应。 ReduxSelectors are then used to show the specific changes on every screen.然后使用 ReduxSelector 显示每个屏幕上的特定更改。

Do explore:探索:

https://pub.dev/packages/async_redux https://pub.dev/packages/async_redux

https://pub.dev/packages/provider_for_redux https://pub.dev/packages/provider_for_redux

Extensive documentation is available.有大量文档可用。

https://www.fireship.io has some interesting content as well regarding state management. https://www.fireship.io也有一些关于 state 管理的有趣内容。

You can use bloc package to handle the state of a subtree (in this case with Menu as root)您可以使用bloc package 来处理子树的 state(在这种情况下,菜单作为根)

Here an example:这里有一个例子:

class MenuBloc extends Bloc<int, int> {
  MenuBloc() : super(0);

  @override
  Stream<int> mapEventToState(int event) async* {
    yield event;
}


class Menu extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider<MenuBloc>(
      create: (context) => MenuBloc(),
      child: Column(
        children: [
          MenuIcon(menuIndex 0),
          MenuIcon(menuIndex: 1),
          MenuIcon(menuIndex: 2),
        ],
      ),
    );
  }
}

class MenuIcon extends StatelessWidget {
  final int menuIndex;

  const MenuIcon({Key key, this.menuIndex}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => _updateState(context),
      child:
          BlocBuilder<MenuBloc, int>(builder: (context, state) {
            final isActive = menuIndex == state;
        return Container();
      }),
    );
  }

  void _updateState(BuildContext context) {
    BlocProvider.of<MenuBloc>(context).add(menuIndex);
  }
}

If you need to do something anywhere in the subtree when you click on a MenuIcon, you can use a BlocListener that triggers every time the state changes如果您需要在单击 MenuIcon 时在子树中的任何位置执行某些操作,则可以使用 BlocListener 每次 state 更改时触发

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在颤动中从父小部件重置子小部件 - Reset child widget from parent widget in flutter Flutter:当小部件没有父/子关系时,如何从小部件 B 调用小部件 A 中的 function? - Flutter: How do I call a function in widget A from widget B when the widgets do not have a parent/child relationship? 在 Flutter 测试中,是否可以从给定的小部件访问子/父小部件? - Is it possible to access children/parent widgets from a given widget, in a Flutter test? Flutter:从子小部件设置父小部件状态 - Flutter: set parent widget state from child widget 如何从子小部件调用父小部件中的 function | Flutter - How to Call a function in parent widget from child widget | Flutter 如何将数据从子状态小部件传递到 Flutter 中的父小部件 - How to pass data from a child Stateful widget to Parent Widget in Flutter 如何在flutter中从父小部件调用子小部件的initState()方法 - How to Invoke initState() method of child widget from parent widget in flutter 如何从 Flutter 中的子小部件调用父小部件 function - How to call parent widget function from child widget in Flutter 我有一个父小部件,其中包含多个子小部件,每个小部件都包含一个复选框。 如何检查父小部件中的每个复选框? - I have a parent widget that contains multiple child widgets which each include a checkbox. How can I check every checkbox from the parent widget? 在 flutter 中将小部件传递给子小部件的最佳方式 - Best way to pass widgets to child widget in flutter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM