Drag Selectable ListView
A Flutter ListView that supports drag-to-select multiple items with customizable selection UI and smooth interaction.
Features
✨ Drag Selection: Select multiple items by dragging across them
🎨 Customizable UI: Custom checkbox builders and item layouts
🎯 Flexible Selection: Support for both tap and drag selection modes
⚡ Performance Optimized: Efficient state management with Provider pattern
🎛️ Configurable: Optional haptic feedback
Demo

Getting Started
Installation
Add this to your package's pubspec.yaml file:
dependencies:
drag_selectable_listview: ^2.0.0
Then run:
flutter pub get
Complete Example
Here's a complete working example showing how to use DragSelectableListView:
class DemoPage extends StatefulWidget {
const DemoPage({super.key});
@override
State<DemoPage> createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> {
int itemCount = 100;
late DragSelectableProvider provider;
@override
void initState() {
super.initState();
List<bool> initialSelection = List.generate(itemCount, (_) => false);
provider = DragSelectableProvider(initialSelection);
}
void _showToast() {
Set<int> set = {};
for (int i = 0; i < provider.selected.length; i++) {
if (provider.selected[i]) {
set.add(i);
}
}
// 显示Toast展示选中的元素
String message;
if (set.isEmpty) {
message = "没有选中任何元素";
} else {
message = "选中的元素: ${set.toList().join(', ')}";
}
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
duration: Duration(seconds: 2),
behavior: SnackBarBehavior.floating,
),
);
}
@override
void dispose() {
provider.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Demo")),
body: Column(
children: [
ElevatedButton(
onPressed: () {
_showToast();
},
child: Text("collect"),
),
Expanded(
child: DragSelectableListView(
provider: provider,
itemCount: itemCount,
itemHeight: 40,
checkboxWidth: 40,
touchSlop: 8.0,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
print(index);
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [Text("Item $index")],
),
),
Divider(height: 1),
],
),
);
},
checkboxBuilder:
({
required bool value,
required ValueChanged<bool?> onChanged,
}) => Transform.scale(
scale: 1.2,
child: Checkbox(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0), // 数值越大越圆
),
value: value,
onChanged: onChanged,
),
),
onSelectionChanged: (List<bool> list) {
// print(list);
},
),
),
],
),
);
}
}
API Reference
DragSelectableListView Properties
- provider (DragSelectableProvider): State management provider for selection logic
- itemCount (int): Total number of items in the list
- itemBuilder (IndexedWidgetBuilder): Builder function for list items
- onSelectionChanged (ValueChanged<List
- checkboxBuilder (Function): Builder for custom checkbox widgets
- itemHeight (double): Height of each list item
- checkboxWidth (double): Width allocated for checkbox area
- touchSlop (double): Minimum drag distance to activate selection mode
- enableHapticFeedback (bool): Enable/disable haptic feedback during selection
DragSelectableProvider Properties
- selected (List
- isSelecting (bool): Whether drag selection mode is active
- scrollController (ScrollController): Controller for list scrolling
Selection Behavior
- Tap Selection: Tap individual checkboxes to toggle selection
- Drag Selection: Press and drag across items to select/deselect ranges
- Important: Drag selection only activates when gesture starts within checkbox area (defined by
checkboxWidth) - Gestures starting outside checkbox area trigger normal list scrolling
- Important: Drag selection only activates when gesture starts within checkbox area (defined by
- Selection Toggle: Drag selection toggles items (selected ↔ deselected)
- Visual Feedback: Selection changes are immediately reflected in the UI
Testing
This package includes comprehensive tests covering:
- Widget rendering and layout
- Selection state management
- Provider functionality
- Parameter validation
- Edge cases and boundary conditions
- Resource cleanup and disposal
The test suite includes:
- Unit Tests: 17 tests covering all provider functionality
- Test Coverage: 100% coverage of core components
- Documentation: Complete testing guide in TESTING.md
Run tests with:
flutter test
Bug Reports
Please file bug reports with:
- Clear description of the issue
- Steps to reproduce
- Expected vs actual behavior
- Flutter version and device information
What's New in v2.0.0
🚀 Major Improvements
- Enhanced State Management: Improved Provider pattern implementation
- Better Performance: Optimized widget rebuilds with selective listening
- Comprehensive Testing: Added complete test suite with 17 tests
🔧 Breaking Changes
- Updated API to use
DragSelectableProviderfor state management - Changed
onSelectionChangedcallback to useList<bool>instead ofSet<int> - Improved constructor parameter validation
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
If you have any questions or need help, please open an issue on GitHub.
Made with ❤️ by the Flutter community