Flutter项目选择项插件item_selector的使用

Flutter项目选择项插件item_selector的使用

简介

item_selector 是一个通用的Flutter选择项插件,支持在 ListViewGridViewRowColumn 或其他可以包含索引子组件的父组件中进行选择。它支持单击选择和长按拖动多选,并且具有自动滚动功能。

预览

以下是 item_selector 在不同布局中的效果预览:

ListView GridView
ListView GridView
Column 自定义布局
Column Custom

使用方法

要使用 item_selector 插件,首先需要在 pubspec.yaml 文件中添加依赖:

dependencies:
  item_selector: ^最新版本号

然后,在 Dart 代码中导入并使用该插件。以下是一个完整的示例代码,展示了如何在 ListViewGridViewColumn 中使用 item_selector

完整示例代码

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:item_selector/item_selector.dart';

void main() => runApp(ExampleApp());

// 定义页面数据
final pages = <PageData>[
  PageData(
    title: 'Column',
    icon: Icons.view_agenda,
    builder: (_) => ColumnPage(),
  ),
  PageData(
    title: 'ListView',
    icon: Icons.view_headline,
    builder: (_) => ListViewPage(),
  ),
  PageData(
    title: 'GridView',
    icon: Icons.view_module,
    builder: (_) => GridViewPage(),
  ),
];

class PageData {
  const PageData({this.title, this.icon, this.builder});
  final String? title;
  final IconData? icon;
  final WidgetBuilder? builder;
}

// 主应用类
class ExampleApp extends StatefulWidget {
  [@override](/user/override)
  _ExampleAppState createState() => _ExampleAppState();
}

class _ExampleAppState extends State<ExampleApp> {
  int currentPage = 0;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Item Selector',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Item Selector + ${pages[currentPage].title}'),
        ),
        body: AnimatedSwitcher(
          duration: Duration(milliseconds: 246),
          child: Container(
            key: ValueKey<int>(currentPage),
            child: pages[currentPage].builder!(context),
          ),
        ),
        bottomNavigationBar: BottomNavigationBar(
          currentIndex: currentPage,
          onTap: (index) => setState(() => currentPage = index),
          items: pages
              .map((page) => BottomNavigationBarItem(
                    icon: Icon(page.icon!),
                    title: Text(page.title!),
                  ))
              .toList(),
        ),
      ),
    );
  }
}

// 构建列表项
Widget buildListItem(BuildContext context, int index, bool selected) {
  return Card(
    margin: EdgeInsets.all(10),
    elevation: selected ? 2 : 10, // 选中时降低阴影效果
    child: ListTile(
      leading: FlutterLogo(), // 列表项前的图标
      contentPadding: EdgeInsets.all(10),
      title: Text(index.toString()), // 显示索引
    ),
  );
}

// Column 页面
class ColumnPage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ItemSelectionController(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: List.generate(4, (index) {
          return ItemSelectionBuilder(
            index: index,
            builder: buildListItem, // 使用 buildListItem 构建每个项
          );
        }),
      ),
    );
  }
}

// ListView 页面
class ListViewPage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ItemSelectionController(
      child: ListView.builder(
        itemCount: 100, // 生成100个列表项
        itemBuilder: (BuildContext context, int index) {
          return ItemSelectionBuilder(
            index: index,
            builder: buildListItem, // 使用 buildListItem 构建每个项
          );
        },
      ),
    );
  }
}

// 构建网格项
Widget buildGridItem(BuildContext context, int index, bool selected) {
  return Card(
    margin: EdgeInsets.all(10),
    elevation: selected ? 2 : 10, // 选中时降低阴影效果
    child: GridTile(
      child: Center(child: FlutterLogo()), // 网格项中的图标
      footer: Padding(
        padding: const EdgeInsets.all(2),
        child: Text(
          index.toString(), // 显示索引
          textAlign: TextAlign.end,
        ),
      ),
    ),
  );
}

// GridView 页面
class GridViewPage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    final selection = RectSelection(4); // 创建矩形选择器
    return ItemSelectionController(
      selection: selection,
      child: GridView.count(
        crossAxisCount: 4, // 每行4个网格项
        mainAxisSpacing: 4, // 主轴间距
        crossAxisSpacing: 4, // 交叉轴间距
        children: List.generate(100, (int index) {
          return ItemSelectionBuilder(
            index: index,
            builder: buildGridItem, // 使用 buildGridItem 构建每个项
          );
        }),
      ),
      onSelectionStart: selection.start, // 开始选择时调用
      onSelectionUpdate: selection.update, // 更新选择时调用
    );
  }
}

// 矩形选择器类
class RectSelection extends ItemSelection {
  RectSelection(this.columns);

  final int columns; // 每行的列数
  ItemSelection oldSelection = ItemSelection();

  int rowAt(int index) => index ~/ columns; // 计算行号
  int columnAt(int index) => index % columns; // 计算列号
  int indexAt(int row, int column) => column + row * columns; // 计算索引

  bool start(int start, int end) {
    oldSelection = ItemSelection(start, end);
    return false;
  }

  bool update(int start, int end) {
    // 计算矩形选择区域的边界
    final startRow = rowAt(min(start, end));
    final endRow = rowAt(max(start, end));
    final startColumn = columnAt(min(start, end));
    final endColumn = columnAt(max(start, end));

    // 构造新的矩形选择区域
    final newSelection = ItemSelection();
    for (int r = startRow; r <= endRow; ++r) {
      final startIndex = indexAt(r, startColumn);
      final endIndex = indexAt(r, endColumn);
      newSelection.add(startIndex, endIndex);
    }

    // 应用选择变化
    addAll(ItemSelection.copy(newSelection)..removeAll(oldSelection));
    removeAll(ItemSelection.copy(oldSelection)..removeAll(newSelection));

    oldSelection = newSelection;
    return true;
  }
}

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用item_selector插件的示例代码。item_selector是一个用于选择单个或多个项目的Flutter插件。

首先,确保你的Flutter项目已经添加了item_selector依赖。在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  item_selector: ^最新版本号  # 请替换为实际可用的最新版本号

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

接下来,在你的Flutter项目中,你可以按照以下步骤使用item_selector

  1. 导入依赖
import 'package:flutter/material.dart';
import 'package:item_selector/item_selector.dart';
  1. 定义数据

假设我们有一个简单的字符串列表作为选择项的数据源。

List<String> items = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'];
  1. 创建ItemSelector

在你的Scaffold或任何其他布局小部件中,添加ItemSelector

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> selectedItems = [];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Item Selector Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Expanded(
                child: ItemSelector<String>(
                  items: items,
                  initialSelectedItems: [],
                  onSelectedItemsChanged: (selectedItems) {
                    setState(() {
                      this.selectedItems = selectedItems;
                    });
                  },
                  itemBuilder: (context, item) {
                    return ListTile(
                      title: Text(item),
                    );
                  },
                ),
              ),
              SizedBox(height: 20),
              Text(
                'Selected Items: ${selectedItems.join(", ")}',
                style: TextStyle(fontSize: 20),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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

在这个示例中:

  • items:包含所有可供选择的项。
  • initialSelectedItems:初始化时选中的项,这里为空列表表示没有默认选中的项。
  • onSelectedItemsChanged:当选中项发生变化时的回调函数,这里我们用它来更新selectedItems状态。
  • itemBuilder:用于构建每个项的UI,这里我们简单地使用ListTile来显示每个项。

运行这个代码,你会看到一个简单的界面,其中列出了所有项,并且可以选择一个或多个项。选中的项会显示在下方的文本中。

这个示例展示了如何使用item_selector插件来创建一个简单的多选列表。你可以根据实际需求进一步自定义和扩展这个示例。

回到顶部