Flutter多选范围选择插件multiselect_scope的使用

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

Flutter多选范围选择插件multiselect_scope的使用

multiselect_scope

这是一个用于多个选择和跟踪选定项(全选、清除、反转选择等)的包。

演示

使用方法

1. 创建 MultiselectController

如果您需要在MultiselectScope外部管理选择,则创建MultiselectController

final multiselectController = MultiselectController();

2. 包装多子组件

将您的多子组件(如ListViewGridView或其他)包装在MultiselectScope中。将域对象列表(例如CarsEmployees)传递给dataSource。不要忘记为泛型参数传递域类型(如果域类型是String,则为MultiselectScope<String>)。现在让我们看看代码中的注释。

MultiselectScope<String>(
  controller: multiselectController,
  dataSource: items,
  // 如果您希望用户点击返回按钮时自动清除选择,请将此设置为true
  clearSelectionOnPop: true,
  // 当您更新[dataSource]时,已选中的索引将更新
  // 以便新[dataSource]中的相同元素仍然被选中
  keepSelectedItemsBetweenUpdates: true,
  initialSelectedIndexes: [1, 3],
  // 在选择更改时调用的回调
  onSelectionChanged: (indexes, items) {
    // 处理选择变化逻辑
  },
  child: ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        // 获取控制器链接  
        final controller = MultiselectScope.controllerOf(context);

        final itemIsSelected = controller.isSelected(index);

        return InkWell(
          // 您可以根据需要实现选择逻辑
          // 例如,在长按后开始选择模式  
          onLongPress: () {
            if (!controller.selectionAttached) {
              controller.select(index);
            }
          },
          onTap: () {
            if (controller.selectionAttached) {
              controller.select(index);
            }
          },
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Container(
              // 根据是否选中来改变颜色 
              color: itemIsSelected ? Theme.of(context).primaryColor : null,
              child: Text(
                items[index],
                style: TextStyle(fontSize: 22),
              ),
            ),
          ),
        );
      }),
)

3. 控制选择

获取作用域内的控制器链接:

final controller = MultiselectScope.controllerOf(context);

如果您想在作用域外部使用控制器,那么获取之前创建的链接(multiselectController

管理选择:

multiselectController.selectAll(); // 全选
multiselectController.select(0); // 选择第0项
multiselectController.invertSelection(); // 反转选择
multiselectController.clearSelection(); // 清除选择
multiselectController.setSelectedIndexes([1, 2, 3]); // 设置特定索引为选中状态

4. 获取已选项

final selectedItems = multiselectController.getSelectedItems().cast<String>();

或者检查项目是否被选中:

final itemIsSelected = controller.isSelected(index);

示例代码

下面是一个完整的示例代码,展示了如何使用multiselect_scope进行多选操作。

import 'dart:math';

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

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

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

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);

  final String? title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late List<String> _items;
  late MultiselectController _multiselectController;
  late Random random;

  @override
  void initState() {
    super.initState();
    random = Random();
    _items = List.generate(10, (index) => 'Item $index');

    _multiselectController = MultiselectController();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: MultiselectScope<String>(
        controller: _multiselectController,
        dataSource: _items,
        clearSelectionOnPop: true,
        keepSelectedItemsBetweenUpdates: true,
        initialSelectedIndexes: [1, 3],
        onSelectionChanged: (indexes, items) {
          debugPrint('Custom listener invoked! Indexes: $indexes Items: $items');
        },
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Expanded(
                child: ListView.builder(
                    itemCount: _items.length,
                    itemBuilder: (context, index) {
                      final controller = MultiselectScope.controllerOf(context);

                      final itemIsSelected = controller.isSelected(index);

                      return InkWell(
                        onLongPress: () {
                          if (!controller.selectionAttached) {
                            controller.select(index);
                          }
                        },
                        onTap: () {
                          debugPrint('Item is selected: $itemIsSelected');

                          if (controller.selectionAttached) {
                            controller.select(index);
                          }
                        },
                        child: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Container(
                            color: itemIsSelected
                                ? Theme.of(context).primaryColor
                                : null,
                            child: Text(
                              _items[index],
                              style: TextStyle(fontSize: 22),
                            ),
                          ),
                        ),
                      );
                    }),
              ),
              Wrap(
                children: <Widget>[
                  RawMaterialButton(
                    child: Text('Add rand'),
                    padding: EdgeInsets.symmetric(horizontal: 8.0),
                    fillColor: Colors.blueGrey,
                    onPressed: () {
                      setState(() {
                        final randItem =
                            'RandItem' + random.nextInt(256).toString();

                        final randomIndex =
                            _items.isEmpty ? 0 : random.nextInt(_items.length);
                        _items.insert(randomIndex, randItem);
                      });
                    },
                  ),
                  RawMaterialButton(
                    padding: EdgeInsets.symmetric(horizontal: 8.0),
                    child: Text('Remove rand'),
                    fillColor: Colors.lightGreen,
                    onPressed: () {
                      setState(() {
                        if (_items.length == 1) {
                          _items.removeAt(0);
                        } else {
                          _items.removeAt(random.nextInt(_items.length - 1));
                        }
                      });
                    },
                  ),
                  RawMaterialButton(
                    padding: EdgeInsets.symmetric(horizontal: 8.0),
                    fillColor: Colors.blueGrey,
                    child: Text('Delete'),
                    onPressed: () {
                      setState(() {
                        final itemsToRemove = _multiselectController
                            .getSelectedItems()
                            .cast<String>();

                        _items = _items
                            .where(
                                (element) => !itemsToRemove.contains(element))
                            .toList();
                      });
                    },
                  ),
                  RawMaterialButton(
                    padding: EdgeInsets.symmetric(horizontal: 8.0),
                    child: Text('Select 0'),
                    fillColor: Colors.lightGreen,
                    onPressed: () {
                      _multiselectController.select(0);
                    },
                  ),
                  RawMaterialButton(
                    padding: EdgeInsets.symmetric(horizontal: 8.0),
                    child: Text('Select all'),
                    fillColor: Colors.amber,
                    onPressed: () {
                      _multiselectController.selectAll();
                    },
                  ),
                  RawMaterialButton(
                    padding: EdgeInsets.symmetric(horizontal: 8.0),
                    child: Text('Invert'),
                    fillColor: Colors.tealAccent,
                    onPressed: () {
                      _multiselectController.invertSelection();
                    },
                  ),
                  RawMaterialButton(
                    padding: EdgeInsets.symmetric(horizontal: 8.0),
                    child: Text('Clear'),
                    fillColor: Colors.deepPurpleAccent,
                    onPressed: () {
                      _multiselectController.clearSelection();
                    },
                  ),
                ],
              )
            ],
          ),
        ),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

这个示例展示了如何在Flutter应用中使用multiselect_scope插件来实现多选功能,并提供了添加、删除随机项、删除选中项、选择特定项、全选、反选和清空选择等功能。


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

1 回复

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


当然,以下是如何在Flutter中使用multiselect_scope插件来实现多选范围选择的代码示例。multiselect_scope是一个用于实现多选功能的Flutter插件,特别适用于需要在列表中选择多个项目的情况。

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

dependencies:
  flutter:
    sdk: flutter
  multiselect_scope: ^latest_version  # 替换为实际的最新版本号

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

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

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  final List<String> items = List<String>.generate(20, (i) => "Item ${i + 1}");
  List<String> selectedItems = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('MultiSelect Scope Demo'),
      ),
      body: MultiSelectScope(
        list: items,
        selectedList: selectedItems,
        itemBuilder: (context, index, isSelected) {
          return Card(
            child: ListTile(
              leading: Checkbox(
                value: isSelected,
                onChanged: (newValue) {
                  setState(() {
                    if (newValue) {
                      selectedItems.add(items[index]);
                    } else {
                      selectedItems.remove(items[index]);
                    }
                  });
                },
              ),
              title: Text(items[index]),
            ),
          );
        },
        onItemSelected: (index, isSelected) {
          setState(() {
            if (isSelected) {
              selectedItems.add(items[index]);
            } else {
              selectedItems.remove(items[index]);
            }
          });
        },
        onRangeSelected: (startIndex, endIndex, isSelected) {
          setState(() {
            if (isSelected) {
              for (int i = startIndex; i <= endIndex; i++) {
                if (!selectedItems.contains(items[i])) {
                  selectedItems.add(items[i]);
                }
              }
            } else {
              for (int i = startIndex; i <= endIndex; i++) {
                if (selectedItems.contains(items[i])) {
                  selectedItems.remove(items[i]);
                }
              }
            }
          });
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          showDialog(
            context: context,
            builder: (context) {
              return AlertDialog(
                title: Text('Selected Items'),
                content: SingleChildScrollView(
                  child: ListBody(
                    children: selectedItems.map((item) => Text(item)).toList(),
                  ),
                ),
                actions: <Widget>[
                  TextButton(
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                    child: Text('OK'),
                  ),
                ],
              );
            },
          );
        },
        tooltip: 'Show Selected Items',
        child: Icon(Icons.list),
      ),
    );
  }
}

解释

  1. 依赖添加:确保在pubspec.yaml中添加了multiselect_scope依赖。

  2. 构建UI

    • 使用Scaffold构建基础页面结构。
    • 使用MultiSelectScope包裹列表,MultiSelectScope提供多选功能。
    • itemBuilder用于构建每个列表项,这里使用CardListTile来展示每个项目,并在前面添加Checkbox
    • onItemSelectedonRangeSelected用于处理单个项目和范围选择。
  3. 显示选中的项目

    • 使用FloatingActionButton触发对话框显示选中的项目。

这个示例展示了如何在Flutter中使用multiselect_scope插件实现基本的多选功能。你可以根据需要进行进一步的自定义和扩展。

回到顶部