Flutter中使用FilterButtonWidget筛选后如何展示用户已选筛选值
实现方案
- 第一步:改造页面状态管理,不直接修改常量配置
你当前constants里存储的是筛选选项的初始配置,不要直接修改它的值,在筛选页的State类中定义可变的状态变量存储用户选中结果:
// 筛选页State内定义变量 late Map<String, bool> selectedBrands; late RangeValues selectedPriceRange; // 适配价格区间选择场景 @override void initState() { super.initState(); // 初始化时深拷贝常量配置作为初始值 selectedBrands = Map.from(constants.brand); selectedPriceRange = RangeValues(constants.price.first, constants.price.last); }
- 第二步:给FilterButtonWidget新增选中回调
改造FilterButtonWidget组件,新增选中结果回调参数,用户在BottomSheet内选完筛选项点击确认时,把最新的选中结果回传给父页面:
// FilterButtonWidget定义新增回调参数 class FilterButtonWidget extends StatelessWidget { final String title; final dynamic item; final String type; // 新增回调,选中结果变更时触发 final Function(dynamic selectedValue) onSelectionChanged; const FilterButtonWidget({ super.key, required this.title, required this.item, required this.type, required this.onSelectionChanged, }); // 原有BottomSheet逻辑中,用户点击确认按钮时调用回调回传结果 // 示例:品牌选择确认时调用 onSelectionChanged(当前选中的brand Map) // 价格选择确认时调用 onSelectionChanged(用户选中的RangeValues区间) }
父页面使用组件时绑定回调更新本地状态:
Padding( padding: const EdgeInsets.all(15.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ // 后续在这里加已选标签展示区域 FilterButtonWidget( title: 'Brand', item: selectedBrands, type: 'brand', onSelectionChanged: (newSelectedBrands) { setState(() { selectedBrands = newSelectedBrands; }); }, ), FilterButtonWidget( title: 'Price', item: constants.price, type: 'price', onSelectionChanged: (newPriceRange) { setState(() { selectedPriceRange = newPriceRange; }); }, ), ], ), )
- 第三步:实现已选标签展示区域
在FilterButton组件上方新增已选标签展示区,用Wrap组件排列标签,支持点击取消单个筛选项:
// 把该方法加到Column的第一个子组件位置 Widget _buildSelectedTags() { List<Widget> tags = []; // 生成已选品牌标签 selectedBrands.forEach((brandName, isSelected) { if (isSelected) { tags.add(Container( margin: const EdgeInsets.only(right: 8, bottom: 8), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.blue.shade100, borderRadius: BorderRadius.circular(20), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text(brandName, style: const TextStyle(color: Colors.blue, fontSize: 12)), const SizedBox(width: 4), GestureDetector( onTap: () => setState(() => selectedBrands[brandName] = false), child: const Icon(Icons.close, size: 14, color: Colors.blue), ) ], ), )); } }); // 生成已选价格标签,非全选状态才展示 if (selectedPriceRange.start != constants.price.first || selectedPriceRange.end != constants.price.last) { tags.add(Container( margin: const EdgeInsets.only(right: 8, bottom: 8), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.blue.shade100, borderRadius: BorderRadius.circular(20), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text('${selectedPriceRange.start} - ${selectedPriceRange.end}元', style: const TextStyle(color: Colors.blue, fontSize: 12)), const SizedBox(width: 4), GestureDetector( onTap: () => setState(() => selectedPriceRange = RangeValues(constants.price.first, constants.price.last)), child: const Icon(Icons.close, size: 14, color: Colors.blue), ) ], ), )); } // 无已选项时返回空占位 if (tags.isEmpty) return const SizedBox.shrink(); return Wrap(children: tags); }
- 可选优化:给FilterButton增加已选数量提示
可以在筛选按钮的标题上展示当前维度已选数量,比如选中1个品牌时按钮显示「Brand(1)」,用户不用展开面板也能感知该维度有没有选中值。
内容的提问来源于stack exchange,提问作者Berkin
相关产品推荐
相关产品推荐

