A lightweight Flutter wrapper to selectively absorb or allow gesture interactions
selective_gesture_wrapper
selective_gesture_wrapper is a simple but powerful widget that lets you selectively absorb gestures on parts of your widget tree. Perfect for editors, canvases, and tools where only selected items should respond to drag, scale, or tap events.
🚀 Features
- ✅ Conditionally absorb gesture events using a simple flag
- ✅ Works with
GestureDetector,Draggable,InteractiveViewer, and more - ✅ Lightweight and dependency-free
- ✅ Fully compatible with Flutter's rendering pipeline
🛠 Installation
flutter pub add selective_gesture_wrapper
📦 Import
import 'package:selective_gesture_wrapper/selective_gesture_wrapper.dart';
🌍 Basic Usage
void main() {
SelectiveGestureWrapper(
absorbGestures: true, // or false to allow gestures
child: GestureDetector(
onTap: () => print("Tapped"),
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
);
}
💡 Basic Example
void main() => runApp(const MaterialApp(home: EditorPage()));
class EditorPage extends StatefulWidget {
const EditorPage({super.key});
@override
State<EditorPage> createState() => _EditorPageState();
}
class _EditorPageState extends State<EditorPage> {
int? selectedId;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: List.generate(3, (index) {
return SelectableDraggableWidget(
key: ValueKey(index),
id: index,
isSelected: selectedId == index,
onSelect: () => setState(() => selectedId = index),
child: Container(
width: 100,
height: 100,
color: Colors.primaries[index],
child: Center(child: Text('Box $index')),
),
);
}),
),
);
}
}
class SelectableDraggableWidget extends StatefulWidget {
final Widget child;
final bool isSelected;
final VoidCallback onSelect;
final int id;
const SelectableDraggableWidget({
super.key,
required this.child,
required this.isSelected,
required this.onSelect,
required this.id,
});
@override
State<SelectableDraggableWidget> createState() =>
_SelectableDraggableWidgetState();
}
class _SelectableDraggableWidgetState extends State<SelectableDraggableWidget> {
Offset position = const Offset(50.0, 50.0);
double scale = 1.0;
@override
Widget build(BuildContext context) {
return Positioned(
left: position.dx,
top: position.dy,
child: SelectiveGestureWrapper(
absorbGestures: !widget.isSelected,
child: GestureDetector(
onTap: widget.onSelect,
onScaleUpdate: widget.isSelected
? (details) {
setState(() {
scale = details.scale;
position += details.focalPointDelta;
});
}
: null,
child: Transform.scale(
scale: scale,
child: Container(
decoration: BoxDecoration(
border: widget.isSelected
? Border.all(color: Colors.blue, width: 3)
: null,
),
child: widget.child,
),
),
),
),
);
}
}
📃 License
Licensed under the MIT License
❤️ Contribute
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
GitHub → https://github.com/sourabhappdev/selective_gesture_wrapper/tree/main