Flutter拖拽批量选择drag_selectable_listview

18 阅读2分钟

🚀 Flutter 实现“拖拽批量选择 ListView”,我封装成了一个通用组件

在 Flutter 开发中,有一个非常常见但官方不支持的交互

👉 像文件管理器一样,通过“拖拽”批量选择列表项

Demo

demo.gif

比如:

  • 多选图片
  • 批量删除消息
  • 选择文件列表

但问题是👇

❗ Flutter 原生 ListView 不支持拖拽选择


🤔 常见方案有什么问题?

一般大家会这样做:

方案一:一个个点击 Checkbox

👉 缺点:

  • 操作成本高(用户要点很多次)
  • 体验差

方案二:长按进入多选模式

👉 缺点:

  • 仍然是“逐个点”
  • 不支持滑动选择

方案三:自己实现拖拽手势

👉 现实是:

  • 手势冲突(和 ListView 滚动冲突)
  • 自动滚动难处理
  • 选中区间计算复杂

👉 写过的人都知道:非常容易踩坑


💡 我的解决方案

我做了一个组件:

👉 DragSelectableListView

支持👇

  • ✅ 拖拽批量选择
  • ✅ 自动滚动
  • ✅ Checkbox 自定义
  • ✅ 兼容 ListView.builder
  • ✅ Tap + Drag 混合选择

🎬 效果演示

Demo

👉 核心体验:

  • 从一个 item 开始拖
  • 滑动经过的 item 自动选中 / 取消
  • 手势非常顺滑

⚡ 如何使用(非常简单)

只需要 3 步:

1️⃣ 添加依赖

dependencies:
  drag_selectable_listview: ^1.0.1
flutter pub get

2️⃣ 基础用法

DragSelectableListView(
  itemCount: 60,
  selected: selected,
  onSelectionChanged: (e) {
    setState(() {
      selected = e;
    });
  },
  itemBuilder: (context, index) {
    return Text("Item $index");
  },
)

3️⃣ 自定义 UI(可选)

checkboxBuilder: ({
  required bool value,
  required ValueChanged<bool?> onChanged,
}) {
  return Checkbox(
    value: value,
    onChanged: onChanged,
  );
}

🧠 核心设计思路(重点)

这个组件最难的其实不是 UI,而是👇


1️⃣ 手势冲突处理

问题:

👉 拖拽选择 vs ListView 滚动

解决方案:

  • 只在 checkbox 区域内 启动拖拽选择
  • 其他区域仍然走 ListView 滚动

👉 这样用户不会误触


2️⃣ 区间选中计算

拖拽本质是:

startIndex → currentIndex

然后:

[min, max] 区间全部 toggle

3️⃣ 自动滚动(关键体验)

当拖到边界时:

  • 自动触发 scrollController
  • 持续滚动

👉 这个细节决定体验好坏


4️⃣ 状态管理设计

组件是:

👉 受控组件(Controlled Component)

selected: Set<int>
onSelectionChanged: callback

优点:

  • 更灵活
  • 可配合 Provider / Riverpod / Bloc

📊 性能分析

基于:

👉 ListView.builder

所以:

  • ✅ 只渲染可见区域
  • ✅ 支持大数据量(上千条)
  • ✅ 内存占用低

⚠️ 使用注意点

1. 必须在回调中更新状态

onSelectionChanged: (e) {
  setState(() {
    selected = e;
  });
}

2. itemHeight 需要固定

👉 用于计算拖拽命中 index


3. 拖拽只在 checkbox 区域生效

👉 避免和滚动冲突


🚀 适用场景

这个组件适合👇

  • 文件管理器
  • 图片选择器
  • 邮件列表
  • 批量操作列表

📦 开源地址

👉 pub.dev:

pub.dev/packages/dr…

如果觉得有用,欢迎:

  • ⭐ 点个 star
  • 🐛 提 issue
  • 💡 提建议

🧠 一点思考

Flutter 在 UI 表达力上很强,但:

👉 一些“复杂交互组件”仍然需要自己实现

比如:

  • 拖拽排序
  • 区间选择
  • 手势组合

👉 这些恰恰是组件库的价值所在


🎯 后续计划

  • 支持 GridView
  • 支持横向列表
  • 提供更多动画效果

如果你也在做类似交互,欢迎交流 👇