Flutter多选过滤器插件multi_selection_filter的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter多选过滤器插件multi_selection_filter的使用

简介

Multi Selection Filter 是一个功能强大的Flutter插件,允许您在一个对话框中展示一个项目列表,用户可以选择或取消选择这些项目。这个对话框高度可定制,以满足您的需求。

Multi_selection_filter package poster

功能

  • 兼容Flutter 3.13
  • 提供复选框列表,方便项目选择
  • 提供全面的自定义选项
  • 内置搜索功能,快速查找对话框中的项目
  • 可选择显示可移除的芯片,增加用户便利性

Screenshot 1 Screenshot 2

安装

在您的 pubspec.yaml 文件中添加 multi_selection_filter 依赖:

dependencies:
  multi_selection_filter: ^0.0.3

使用方法

1. 创建项目及其初始选择状态的Map

initState 方法中初始化 foodItems Map,用于存储食物项及其初始选择状态:

class _MyHomePageState extends State<MyHomePage> {
  Map<String, bool> foodItems = {};

  [@override](/user/override)
  void initState() {
    super.initState();
    foodItems.putIfAbsent("Aloo Gobi", () => false);
    foodItems.putIfAbsent("Tacos", () => false);
    foodItems.putIfAbsent("Falafel", () => false);
    foodItems.putIfAbsent("Margherita Pizza", () => false);
    foodItems.putIfAbsent("Dal Makhani", () => false);
    foodItems.putIfAbsent("Hot and Sour Soup", () => false);
    foodItems.putIfAbsent("Bruschetta", () => false);
    foodItems.putIfAbsent("Mapo Tofu", () => false);
  }
}

2. 显示对话框

使用 MultiSelectionFilter 小部件来显示对话框,并根据用户的选择更新 foodItems Map:

Widget _buildFilterWidget() {
  return Align(
    alignment: Alignment.topCenter,
    child: MultiSelectionFilter(
      title: "Select Food",
      textListToShow: foodItems.keys.toList(),
      selectedList: foodItems.values.toList(),
      accentColor: const Color(0xFF01b4e4),
      checkboxTitleBG: Colors.black87,
      checkboxCheckColor: Colors.white,
      checkboxTitleTextColor: Colors.white,
      doneButtonBG: const Color(0xFF01b4e4),
      doneButtonTextColor: Colors.white,
      onCheckboxTap: (key, index, isChecked) {
        setState(() {
          foodItems[key] = isChecked;
        });
      },
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Card(
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(8)),
          ),
          color: Colors.blueGrey.shade700,
          elevation: 4,
          child: const Padding(
            padding: EdgeInsets.all(8.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  "Filter Food items",
                  style: TextStyle(
                    color: Colors.white, 
                    fontWeight: FontWeight.w600
                  ),
                ),
                SizedBox(width: 16),
                Icon(
                  Icons.fastfood_rounded,
                  size: 30,
                  color: Colors.white,
                ),
              ],
            ),
          ),
        ),
      ),
    ),
  );
}

3. 显示已选择的项目

根据 foodItems 中的值,显示已选择的项目或提示用户选择项目:

Widget _buildSelectedFoodChip() {
  var selectedFoodItems = foodItems.entries.where((element) => element.value);
  return ListView.builder(
    itemCount: selectedFoodItems.length,
    itemBuilder: (context, index) {
      return Chip(
        onDeleted: () => setState(() {
          foodItems[selectedFoodItems.toList()[index].key] = false;
        }),
        backgroundColor: const Color(0xFFFDCB47),
        labelPadding: const EdgeInsets.only(right: 5),
        label: SizedBox(
          width: MediaQuery.of(context).size.width / 2,
          child: Text(
            selectedFoodItems.toList()[index].key,
            style: const TextStyle(
              color: Colors.black,
            ),
          ),
        ),
        deleteIcon: const Icon(
          Icons.close,
          size: 20,
          color: Colors.black,
        ),
      );
    },
  );
}

Widget _buildNoFoodSelected(BuildContext context) {
  return Center(
    child: Text(
      "Please select Food item",
      style: Theme.of(context)
          .textTheme
          .headlineSmall!
          .copyWith(color: Colors.black54),
    ),
  );
}

4. 完整示例代码

以下是完整的示例代码,展示了如何使用 multi_selection_filter 插件:

import 'package:flutter/material.dart';
import 'package:multi_selection_filter/multi_selection_filter.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "My Favorite Foods",
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      debugShowCheckedModeBanner: false,
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Map<String, bool> foodItems = {};

  [@override](/user/override)
  void initState() {
    super.initState();
    foodItems.putIfAbsent("Aloo Gobi", () => false);
    foodItems.putIfAbsent("Tacos", () => false);
    foodItems.putIfAbsent("Falafel", () => false);
    foodItems.putIfAbsent("Margherita Pizza", () => false);
    foodItems.putIfAbsent("Dal Makhani", () => false);
    foodItems.putIfAbsent("Hot and Sour Soup", () => false);
    foodItems.putIfAbsent("Bruschetta", () => false);
    foodItems.putIfAbsent("Mapo Tofu", () => false);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text("Multi Selection Filter"),
      ),
      body: Column(
        children: [
          const SizedBox(height: 20),
          _buildFilterWidget(),
          const SizedBox(height: 20),
          Expanded(
            child: foodItems.values.contains(true)
                ? _buildSelectedFoodChip()
                : _buildNoFoodSelected(context),
          ),
        ],
      ),
    );
  }

  Widget _buildFilterWidget() {
    return Align(
      alignment: Alignment.topCenter,
      child: MultiSelectionFilter(
        title: "Select Food",
        textListToShow: foodItems.keys.toList(),
        selectedList: foodItems.values.toList(),
        accentColor: const Color(0xFF01b4e4),
        checkboxTitleBG: Colors.black87,
        checkboxCheckColor: Colors.white,
        checkboxTitleTextColor: Colors.white,
        doneButtonBG: const Color(0xFF01b4e4),
        doneButtonTextColor: Colors.white,
        onCheckboxTap: (key, index, isChecked) {
          setState(() {
            foodItems[key] = isChecked;
          });
        },
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Card(
            shape: const RoundedRectangleBorder(
              borderRadius: BorderRadius.all(Radius.circular(8)),
            ),
            color: Colors.blueGrey.shade700,
            elevation: 4,
            child: const Padding(
              padding: EdgeInsets.all(8.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    "Filter Food items",
                    style: TextStyle(
                      color: Colors.white, 
                      fontWeight: FontWeight.w600
                    ),
                  ),
                  SizedBox(width: 16),
                  Icon(
                    Icons.fastfood_rounded,
                    size: 30,
                    color: Colors.white,
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildSelectedFoodChip() {
    var selectedFoodItems = foodItems.entries.where((element) => element.value);
    return ListView.builder(
      itemCount: selectedFoodItems.length,
      itemBuilder: (context, index) {
        return Chip(
          onDeleted: () => setState(() {
            foodItems[selectedFoodItems.toList()[index].key] = false;
          }),
          backgroundColor: const Color(0xFFFDCB47),
          labelPadding: const EdgeInsets.only(right: 5),
          label: SizedBox(
            width: MediaQuery.of(context).size.width / 2,
            child: Text(
              selectedFoodItems.toList()[index].key,
              style: const TextStyle(
                color: Colors.black,
              ),
            ),
          ),
          deleteIcon: const Icon(
            Icons.close,
            size: 20,
            color: Colors.black,
          ),
        );
      },
    );
  }

  Widget _buildNoFoodSelected(BuildContext context) {
    return Center(
      child: Text(
        "Please select Food item",
        style: Theme.of(context)
            .textTheme
            .headlineSmall!
            .copyWith(color: Colors.black54),
      ),
    );
  }
}

更多关于Flutter多选过滤器插件multi_selection_filter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter多选过滤器插件multi_selection_filter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用multi_selection_filter插件的一个简单示例。这个插件允许你创建一个多选过滤器组件,非常适合在选择多个选项时使用。

首先,确保你已经在pubspec.yaml文件中添加了multi_selection_filter依赖:

dependencies:
  flutter:
    sdk: flutter
  multi_selection_filter: ^最新版本号 # 请替换为实际最新版本号

然后,运行flutter pub get来安装依赖。

接下来,你可以在你的Flutter应用中实现这个插件。以下是一个完整的示例代码:

import 'package:flutter/material.dart';
import 'package:multi_selection_filter/multi_selection_filter.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Multi Selection Filter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 定义选项列表
  final List<String> options = [
    'Option 1',
    'Option 2',
    'Option 3',
    'Option 4',
    'Option 5',
  ];

  // 保存选中的选项
  List<String> selectedOptions = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Multi Selection Filter Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            // 使用 MultiSelectionFilter 组件
            MultiSelectionFilter<String>(
              initialSelection: selectedOptions,
              options: options.map((e) => MultiSelectionFilterOption<String>(value: e)).toList(),
              onSelectionChanged: (selected) {
                setState(() {
                  selectedOptions = selected;
                });
              },
              chipDisplay: (value) {
                return Chip(
                  label: Text(value),
                  backgroundColor: Colors.blue.shade100,
                );
              },
              title: Text('Select Options'),
            ),
            SizedBox(height: 20),
            // 显示选中的选项
            Text(
              'Selected Options: ${selectedOptions.join(', ')}',
              style: TextStyle(fontSize: 18),
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们首先定义了一个包含多个选项的列表options
  2. 然后,我们创建了一个MultiSelectionFilter组件,并将选项列表和初始选中的选项传递给它。
  3. onSelectionChanged回调在选项变化时被调用,我们在这里更新selectedOptions列表。
  4. chipDisplay用于自定义选中项的显示样式,这里我们使用了Chip组件。
  5. 最后,我们在页面上显示当前选中的选项。

运行这个示例应用,你将看到一个多选过滤器,你可以从中选择多个选项,并在页面上看到当前选中的选项。

回到顶部