我有一个Menu Stateful Widget,它是多个MenuIcon子widget的父widget,每个MenuIcon返回一个容器。用户可以单独点击MenuIcon widget,当active bool为true时突出显示,否则不突出显示。目前,这一切都在MenuIcon类中控制,但从here阅读来看,这并不是最好的方法,因为每个图标的状态在应用程序中将起重要作用,所以我希望能够在父widget中管理它。但我不确定如何做到这一点,之前链接的教程只有一个父widget->一个子widget,因此很容易从父widget中管理状态。但在这种情况下,由于父widget包含多个具有自己的活动/非活动状态的子widget实例,我想不出简单的方法来做到这一点。
目前我的层次结构如下:
我希望MenuIcons仅管理它们自己的动画,
Menu
类来管理每个MenuIcon
的状态,而HomePage
则保存当前活动的每个MenuIcon
的列表。
Menu
和MenuIcon
类的代码如下:
//----------------- 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,
);
}
}