Flutter多选字段插件multiselect_field的使用

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

Flutter多选字段插件multiselect_field的使用

MultiSelectField 插件介绍

MultiSelectField 是一个为Flutter应用程序定制实现的多选字段。这个库提供了灵活且高度可配置的解决方案,适用于需要本地多选、实时文本过滤和更高级功能的项目。

特性

  • 灵活性:完全控制小部件的设计和行为,允许根据项目需求进行精确定制。
  • 本地多选:无需额外包或复杂修改即可实现多选功能。
  • 高级功能:包括实时文本过滤和以芯片形式显示选定项,增强用户体验。
  • 维护和进化:作为自定义实现,它允许随着项目需求的变化轻松适应和发展。
  • 独立性:避免第三方依赖,提高项目稳定性和长期控制。

库信息

可以在 pub.dev 查看此库。

安装

pubspec.yaml 文件中添加依赖:

dependencies:
  multiselect_field: ^1.6.6

然后,使用以下命令安装依赖:

flutter pub get

或者直接添加:

flutter pub add multiselect_field

使用方法

基础示例

下面是一个简单的例子,展示了如何创建一个多选字段并处理选择事件:

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

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiSelectField<Car>(
      data: () => [
        Choice<Car>('Ferrari'),
        Choice<Car>('2', '488 GTB', metadata: Car(103, 27500, 2015)),
        Choice<Car>('3', '458 Italia', metadata: Car(99, 22000, 2009)),
        Choice<Car>('4', 'Portofino', metadata: Car(105, 31000, 2017)),
        Choice<Car>('5', 'California T', metadata: Car(102, 25000, 2016)),
        Choice<Car>('6', 'F8 Tributo', metadata: Car(104, 30000, 2019)),
      ],
      onSelect: (selectedItems) {
        // 处理选中的项目
        print(selectedItems.map((item) => item.value).toList());
      },
      useTextFilter: true, // 启用实时文本过滤
    );
  }
}

属性说明

  • data: 返回 Choice<T> 元素列表的函数。
  • onSelect: 当项目被选中时调用的回调函数。
  • title: 可选标题,取决于选择是否为空。
  • footer: 可选底部组件。
  • singleSelectWidget: 显示单个选中项目的可选组件。
  • multiSelectWidget: 显示多个选中项目的可选组件。
  • defaultData: 默认选中项目的可选列表。
  • singleSelection: 是否仅允许单选,默认为 false
  • useTextFilter: 是否启用实时文本过滤。
  • decoration: 自定义装饰样式。
  • padding: 内边距设置。
  • textStyleSingleSelection: 单选文本样式。

高级示例

这是一个更复杂的例子,展示了更多特性的使用:

MultiSelectField<String>(
  data: () => [
    Choice(key: 'apple', value: 'Apple'),
    Choice(key: 'banana', value: 'Banana'),
    Choice(key: 'orange', value: 'Orange'),
  ],
  defaultData: [Choice(key: 'banana', value: 'Banana')],
  onSelect: (selectedItems, isFromDefaultData) {
    // 更新选择状态
  },
  title: (isEmpty) => Text(isEmpty ? 'Select a fruit' : 'Selected fruits'),
  singleSelection: false,
  useTextFilter: true,
  decoration: BoxDecoration(
    border: Border.all(color: Colors.blue),
    borderRadius: BorderRadius.circular(5),
  ),
  padding: EdgeInsets.all(10),
  multiSelectWidget: (item) => Chip(
    label: Text(item.value),
    onDeleted: () {
      // 移除选中项目
    },
  ),
);

示例应用

这里提供了一个完整的示例应用代码,展示了如何结合各种特性来构建一个多选字段界面:

import 'package:flutter/material.dart';
import 'package:multiselect_field/core/multi_select.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Multiselect field',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'multiselect_field library'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Car? currentCar;

  bool _singleSelection = false;
  bool _useTextForFiltering = false;

  bool _useFooter = false;
  bool _useTitle = false;

  bool _customMultiselectWidget = false;
  bool _customSingleSelectWidget = false;

  bool _useGroupingList = false;

  bool _defaultData = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.primary,
        title: Text(
          widget.title,
          style: const TextStyle(color: Colors.white),
        ),
      ),
      backgroundColor: Theme.of(context).colorScheme.onPrimary,
      body: Padding(
        padding: const EdgeInsets.all(10.0),
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Wrap(
                direction: Axis.horizontal,
                spacing: 3,
                children: [
                  Chip(
                    label: const Text('Use grouping on List'),
                    deleteIcon: _useGroupingList
                        ? const Icon(Icons.check_box)
                        : const Icon(Icons.check_box_outline_blank),
                    onDeleted: () {
                      setState(() {
                        _useGroupingList = !_useGroupingList;
                      });
                    },
                  ),
                  // ...其他Chip控件...
                ],
              ),
              const SizedBox(
                height: 20,
              ),
              MultiSelectField<Car>(
                title: _useTitle
                    ? (val) => const Text(
                          'Optional Title Widget',
                        )
                    : null,
                defaultData: _defaultData ? [choices.first] : [],
                decoration: BoxDecoration(
                    color: Colors.black12,
                    borderRadius: BorderRadius.circular(12)),
                footer:
                    _useFooter ? const Text('Optional Footer Widget') : null,
                data: () => _useGroupingList
                    ? choices
                    : choices
                        .where((e) => e.key != null && e.key!.isNotEmpty)
                        .toList(),
                onSelect: (element, isFromDefault) {
                  setState(() {
                    currentCar =
                        element.isNotEmpty ? element.first.metadata : null;
                  });
                },
                singleSelection: _singleSelection,
                useTextFilter: _useTextForFiltering,
                multiSelectWidget: _customMultiselectWidget
                    ? (choice) {
                        return OutlinedButton(
                            onPressed: () {
                              showDialog(
                                context: context,
                                builder: (context) {
                                  return AlertDialog(
                                    title: Text(choice.value),
                                    content: Column(
                                      mainAxisSize: MainAxisSize.min,
                                      children: [
                                        Text("Price: ${choice.metadata?.price}"),
                                        Text("Year: ${choice.metadata?.year}"),
                                        Text("sold: ${choice.metadata?.totalSold}"),
                                      ],
                                    ),
                                    actions: [
                                      OutlinedButton(
                                        onPressed: () => Navigator.pop(context),
                                        child: const Text('Ok'),
                                      )
                                    ],
                                  );
                                },
                              );
                            },
                            child: Text(choice.value));
                      }
                    : null,
                singleSelectWidget: _customSingleSelectWidget
                    ? (choice) {
                        return Chip(
                          avatar: Text("${choice.metadata?.totalSold}"),
                          label: Text(choice.value),
                        );
                      }
                    : null,
              ),
              if (currentCar != null)
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const SizedBox(
                      height: 20,
                    ),
                    const Text("First car"),
                    Text("Price: ${currentCar!.price}"),
                    Text("Year: ${currentCar!.year}"),
                    Text("sold: ${currentCar!.totalSold}"),
                  ],
                ),
              const SizedBox(
                height: 20,
              ),
              Text(
                "Additional properties",
                style: Theme.of(context).textTheme.titleLarge,
              ),
              ListTile(
                title: Text(
                  "textStyleSingleSelection",
                  style: Theme.of(context).textTheme.titleMedium,
                ),
                subtitle: const Text(
                    "Help to create your own style for single selection using the standard widget. For more flexibility, use singleSelectWidget(Choice){}."),
              ),
              ListTile(
                title: Text(
                  "padding",
                  style: Theme.of(context).textTheme.titleMedium,
                ),
                subtitle: const Text("Apply padding to the entire widget."),
              )
            ],
          ),
        ),
      ),
    );
  }
}

List<Choice<Car>> choices = [
  Choice('', 'Ferrari'),
  Choice('2', '488 GTB', metadata: Car(103, 27500, 2015)),
  Choice('3', '458 Italia', metadata: Car(99, 22000, 2009)),
  Choice('4', 'Portofino', metadata: Car(105, 31000, 2017)),
  Choice('5', 'California T', metadata: Car(102, 25000, 2016)),
  Choice('6', 'F8 Tributo', metadata: Car(104, 30000, 2019)),
  // ...更多选项...
];

class Car {
  final num totalSold;
  final num price;
  final int year;

  Car(this.totalSold, this.price, this.year);
}

通过以上内容,您可以了解 multiselect_field 插件的基本使用方法及其提供的强大功能。希望这些信息能帮助您更好地集成和利用这个插件!


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

1 回复

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


当然,下面是一个关于如何在Flutter中使用multiselect_field插件的示例代码。这个插件允许你在应用中实现多选字段的功能。

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

dependencies:
  flutter:
    sdk: flutter
  multiselect_field: ^^最新版本号(请替换为实际最新版本号)

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

接下来,在你的Flutter应用中,你可以这样使用multiselect_field

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  List<String> _selectedOptions = [];
  final List<String> _options = [
    'Option 1',
    'Option 2',
    'Option 3',
    'Option 4',
    'Option 5',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('MultiSelect Field Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              'Selected Options:',
              style: TextStyle(fontSize: 18),
            ),
            SizedBox(height: 10),
            Wrap(
              children: List.generate(
                _selectedOptions.length,
                (index) => Chip(
                  label: Text(_selectedOptions[index]),
                  backgroundColor: Colors.blue.shade100,
                  deleteIconColor: Colors.grey,
                  onDeleted: () {
                    setState(() {
                      _selectedOptions.removeAt(index);
                    });
                  },
                ),
              ),
            ),
            SizedBox(height: 20),
            MultiSelectField(
              title: 'Select Options',
              initialValue: _selectedOptions,
              options: _options,
              onChanged: (newValue) {
                setState(() {
                  _selectedOptions = newValue;
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

代码解释

  1. 依赖导入:确保导入了multiselect_field包。
  2. 数据准备:在_MyHomePageState类中,我们准备了两个列表:_selectedOptions用于存储用户选择的项目,_options包含所有可供选择的选项。
  3. UI布局
    • 使用Column布局来组织内容。
    • 使用TextWrap小部件来显示已选择的选项。Wrap小部件允许选项在水平空间不足时换行显示。
    • 使用Chip小部件来显示每个已选择的选项,并提供删除按钮。
    • 使用MultiSelectField小部件来显示多选字段。title参数用于设置字段标题,initialValue参数用于设置初始值,options参数包含所有选项,onChanged回调函数在用户选择更改时被调用。

这个示例展示了如何在Flutter应用中使用multiselect_field插件来实现多选字段功能,并动态更新已选择的选项。

回到顶部