【问题标题】:flutter bloc: change color on each item when tap颤动块:点击时更改每个项目的颜色
【发布时间】:2020-07-03 10:02:41
【问题描述】:

我正在尝试使用颤振块,所以我创建了这个块:

class CategoriesBloc extends Bloc<CategoriesEvent, CategoriesState> {
  CategoriesBloc() : super(CategoriesInitial());
  List<CategoriesItem> _catItems = [
    CategoriesItem(id: 1, title: "Sugar", prefixIcon: Icons.access_alarms),
    CategoriesItem(id: 2, title: "Calories", prefixIcon: Icons.access_alarms),
    CategoriesItem(id: 3, title: "Salt", prefixIcon: Icons.access_alarms),
    CategoriesItem(id: 4, title: "Fibre", prefixIcon: Icons.access_alarms),
    CategoriesItem(id: 5, title: "Fat", prefixIcon: Icons.access_alarms)
  ];

  List<CategoriesItem> get items => _catItems;

  @override
  Stream<CategoriesState> mapEventToState(
    CategoriesEvent event,
  ) async* {
    if (event is TopCategoriesEvent) {
      yield* _makeCatList(items);
    }
  }
}

Stream<CategoriesState> _makeCatList(List<CategoriesItem> items) async* {
  yield CategoriesStarted(items);
}

class CategoriesItem {
  final int id;
  final String title;
  final IconData prefixIcon;
  final IconData suffixIcon;
  bool selected;

  CategoriesItem(
      {this.id,
      this.title,
      this.prefixIcon,
      this.suffixIcon,
      this.selected = false});
}

现在在主页上我是这样使用的:

Container(
              height: 80,
              color: Colors.green[500],
              child: BlocBuilder<CategoriesBloc, CategoriesState>(
                  builder: (context, state) {
                if (state is CategoriesInitial) {
                  return Center(
                    child: CircularProgressIndicator(),
                  );
                } else if (state is CategoriesStarted) {
                  return _makeCatItems(state.catItems);
                }
                return Container();
              }),

这是我的 _makeCatItems 方法:

 Widget _makeCatItems(List<CategoriesItem> catItems) {
    print(catItems.length);
    return Container(
      margin: EdgeInsets.only(top: 8.0),
      child: ListView(
        scrollDirection: Axis.horizontal,
        shrinkWrap: true,
        children: catItems
            .map(
              (item) => Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  InkWell(
                    onTap: () {},
                    child: Container(
                        width: 100,
                        height: 40,
                        alignment: Alignment.center,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(8.0),
                          color: Colors.green[300],// change to white when tapped
                        ),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.spaceAround,
                          children: <Widget>[
                            Icon(
                              item.prefixIcon,
                              color: Colors.white,
                            ),
                            Text(
                              item.title,
                              style: TextStyle(color: Colors.white),
                            )
                          ],
                        )),
                  ),
                  SizedBox(
                    width: 16.0,
                  )
                ],
              ),
            )
            .toList(),
      ),
    );
  }

当用户以整体方式单击每个项目时,我如何更改背景项目颜色?

【问题讨论】:

    标签: flutter flutter-bloc


    【解决方案1】:

    您可以在状态中添加一个已点击项目的列表,最初为空列表,添加一个在字段中传递项目的事件并将 BoxDecoration 中的颜色更改为state.tappedItems.contains(item) ? Colors.white : Colors.green[300]。您也需要更改 onTap,如下所示:

    state.tappedItems.contains(item) 
      ? context.bloc<CategoriesBloc>().add(AddItem())  
      : context.bloc<CategoriesBloc>().add(RemoveItem()),
    

    makeCatItems 还需要获取状态作为参数或成为另一个 BlocBuilder,以您感觉更好者为准

    E:

    将状态更改为(您也需要更改 CategoriesState,在字段中添加 final List&lt;CategoriesItem&gt; pressedItems

    Stream<CategoriesState> _makeCatList(List<CategoriesItem> items, List<CategoriesItem> pressedItems) async* {
      yield CategoriesStarted(items, pressedItems);
    }
    

    然后你需要添加事件(CategoryRemoved 就差不多了,复制改名字就好了)

    class CategoryAdded extends CategoryEvent {
      final CategoryItem item;
    
      CategoryAdded(CategoryItem item);
    }
    

    所以你有状态和事件,现在 bloc 需要处理变化。

      @override
      Stream<CategoriesState> mapEventToState(
        CategoriesEvent event,
      ) async* {
        if (event is TopCategoriesEvent) {
          yield* _makeCatList(items);
        } else if (event is CategoryAdded) {
          yield CategoryState(state.items, state.pressedItems..add(event.item));
        } else if (event is CategoryRemoved {
          yield CategoryState(state.items, state.pressedItems..remove(event.item));
        }
      }
    

    现在你的逻辑已经设置好了,现在你只需要更改小部件

     Widget _makeCatItems() {
        return BlocBuilder<CategoryBloc, CategoryState>(
          builder: (context, state) => Container(
          margin: EdgeInsets.only(top: 8.0),
          child: ListView(
            scrollDirection: Axis.horizontal,
            shrinkWrap: true,
            children: catItems
                .map(
                  (item) => Row(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: <Widget>[
                      InkWell(
                        onTap: () {context.bloc<CategoryBloc>().add(state.pressedItems.contains(item) ? RemoveCategory(item) : AddCategory(item)},
                        child: Container(
                            width: 100,
                            height: 40,
                            alignment: Alignment.center,
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(8.0),
                              color: state.pressedItems.contains(item) ? Colors.white : Colors.green[300],
                            ),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.spaceAround,
                              children: <Widget>[
                                Icon(
                                  item.prefixIcon,
                                  color: Colors.white,
                                ),
                                Text(
                                  item.title,
                                  style: TextStyle(color: Colors.white),
                                )
                              ],
                            )),
                      ),
                      SizedBox(
                        width: 16.0,
                      )
                    ],
                  ),
                )
                .toList(),
          ),
        );
      );
      }
    

    【讨论】:

    • 可以发小例子吗?@KamilPoniewierski
    • 您好,我已经编辑了答案,这台电脑上没有 Android Studio,所以格式化已关闭,但它应该可以工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    • 2018-08-21
    • 2021-10-08
    相关资源
    最近更新 更多