You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 16:15:29