如何在Flutter中使用Provider实现筛选弹窗的交互逻辑?
基于Provider实现筛选弹窗的状态管理与页面跳转方案
1. 配置Provider依赖
先在pubspec.yaml里添加Provider依赖:
dependencies: flutter: sdk: flutter provider: ^6.0.5 # 可替换为最新稳定版
执行flutter pub get完成依赖安装。
2. 创建筛选状态管理类
新建filter_provider.dart文件,定义统一管理筛选状态的类:
import 'package:flutter/foundation.dart'; class FilterProvider extends ChangeNotifier { // 存储各栏目的选中值 String? selectedOffer; String? selectedDeliveryTime; String? selectedPricing; String? selectedRating; // 更新优惠选项选中状态 void setSelectedOffer(String value) { selectedOffer = value; notifyListeners(); } // 更新配送时间选中状态 void setSelectedDeliveryTime(String value) { selectedDeliveryTime = value; notifyListeners(); } // 更新价格区间选中状态 void setSelectedPricing(String value) { selectedPricing = value; notifyListeners(); } // 更新评分选中状态 void setSelectedRating(String value) { selectedRating = value; notifyListeners(); } // 重置所有筛选条件(可选) void resetFilters() { selectedOffer = null; selectedDeliveryTime = null; selectedPricing = null; selectedRating = null; notifyListeners(); } }
3. 在应用入口注入Provider
修改main.dart,用ChangeNotifierProvider包裹根组件,让全局可访问筛选状态:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'filter_provider.dart'; import 'your_screen_with_dialog.dart'; // 替换为你包含弹窗的页面路径 void main() { runApp( ChangeNotifierProvider( create: (context) => FilterProvider(), child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Filter Demo', home: const YourScreenWithDialog(), ); } }
4. 修改筛选弹窗的逻辑绑定
基于你已完成的弹窗UI,修改选项点击和按钮事件,绑定Provider状态:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'filter_provider.dart'; import 'filtered_results_screen.dart'; // 替换为你的目标页面路径 void showFilterDialog(BuildContext context) { showDialog( context: context, builder: (context) { return Consumer<FilterProvider>( builder: (context, filterProvider, child) { return AlertDialog( title: const Text('Filters'), content: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // OFFERS 栏目 const Text('OFFERS', style: TextStyle(fontWeight: FontWeight.bold)), Wrap( children: ['5% Off', '10% Off', 'Buy 1 Get 1'].map((offer) { return ChoiceChip( label: Text(offer), selected: filterProvider.selectedOffer == offer, onSelected: (selected) { selected ? filterProvider.setSelectedOffer(offer) : filterProvider.setSelectedOffer(null); }, ); }).toList(), ), const SizedBox(height: 16), // DELIVERY-TIME 栏目 const Text('DELIVERY-TIME', style: TextStyle(fontWeight: FontWeight.bold)), Wrap( children: ['15-20 min', '20-30 min', '30+ min'].map((time) { return ChoiceChip( label: Text(time), selected: filterProvider.selectedDeliveryTime == time, onSelected: (selected) { selected ? filterProvider.setSelectedDeliveryTime(time) : filterProvider.setSelectedDeliveryTime(null); }, ); }).toList(), ), const SizedBox(height: 16), // PRICING 栏目 const Text('PRICING', style: TextStyle(fontWeight: FontWeight.bold)), Wrap( children: ['₹0-100', '₹100-200', '₹200+'].map((price) { return ChoiceChip( label: Text(price), selected: filterProvider.selectedPricing == price, onSelected: (selected) { selected ? filterProvider.setSelectedPricing(price) : filterProvider.setSelectedPricing(null); }, ); }).toList(), ), const SizedBox(height: 16), // RATING 栏目 const Text('RATING', style: TextStyle(fontWeight: FontWeight.bold)), Wrap( children: ['4.5+', '4.0+', '3.5+'].map((rating) { return ChoiceChip( label: Text(rating), selected: filterProvider.selectedRating == rating, onSelected: (selected) { selected ? filterProvider.setSelectedRating(rating) : filterProvider.setSelectedRating(null); }, ); }).toList(), ), ], ), ), actions: [ TextButton( onPressed: () { filterProvider.resetFilters(); Navigator.pop(context); }, child: const Text('RESET'), ), ElevatedButton( onPressed: () { Navigator.pop(context); // 跳转到筛选结果页面,直接从Provider读取筛选条件 Navigator.push( context, MaterialPageRoute( builder: (context) => const FilteredResultsScreen(), ), ); }, child: const Text('FILTER'), ), ], ); }, ); }, ); }
5. 在目标页面读取筛选条件
在跳转后的filtered_results_screen.dart中,通过Provider获取筛选参数并使用:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'filter_provider.dart'; class FilteredResultsScreen extends StatelessWidget { const FilteredResultsScreen({super.key}); @override Widget build(BuildContext context) { final filterProvider = Provider.of<FilterProvider>(context); return Scaffold( appBar: AppBar(title: const Text('Filtered Results')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Selected Offer: ${filterProvider.selectedOffer ?? "None"}'), Text('Selected Delivery Time: ${filterProvider.selectedDeliveryTime ?? "None"}'), Text('Selected Pricing: ${filterProvider.selectedPricing ?? "None"}'), Text('Selected Rating: ${filterProvider.selectedRating ?? "None"}'), // 此处可根据筛选条件渲染对应的结果列表 ], ), ), ); } }
关键说明
- 用
Consumer包裹弹窗,确保UI能实时响应选中状态变化(比如ChoiceChip的选中样式更新) - 所有筛选状态统一存储在
FilterProvider中,避免页面间手动传参的繁琐 - 跳转后的页面直接从Provider读取筛选条件,无需额外数据传递
内容的提问来源于stack exchange,提问作者Moses
相关产品推荐
相关产品推荐

