Skip to content

Instantly share code, notes, and snippets.

@awaik
Created August 17, 2022 11:39
Show Gist options
  • Save awaik/7d5b6d6ec644ae844a3740dddc990ed4 to your computer and use it in GitHub Desktop.
Save awaik/7d5b6d6ec644ae844a3740dddc990ed4 to your computer and use it in GitHub Desktop.
Flutter 3.0.5 - Sample code to detect 2 finger swipe vertically using `RawGestureDetector` and `MultiDragGestureRecognizer`.Sample code to detect 2 finger swipe vertically using `RawGestureDetector` and `MultiDragGestureRecognizer`.
// original code is here, this is upadated version for the new Flutter
// https://gist.github.com/guptahitesh121/ca7fa34d73b8b024823c85dd0c7f687d
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Swipe Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const SwipeDemo(),
);
}
}
class SwipeDemo extends StatefulWidget {
const SwipeDemo({Key? key}) : super(key: key);
@override
SwipeDemoState createState() => SwipeDemoState();
}
class SwipeDemoState extends State<SwipeDemo> {
Offset offset = Offset.zero;
@override
Widget build(BuildContext context) {
return SafeArea(
child: TwoFingerPointerWidget(
onUpdate: (details) {
setState(() {
offset += details.delta;
});
},
child: Container(
alignment: Alignment.center,
color: Colors.white,
child: Transform.translate(
offset: offset,
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
),
),
);
}
}
class TwoFingerPointerWidget extends StatelessWidget {
final Widget child;
final OnUpdate onUpdate;
const TwoFingerPointerWidget({
Key? key,
required this.child,
required this.onUpdate,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return RawGestureDetector(
gestures: <Type, GestureRecognizerFactory>{
CustomVerticalMultiDragGestureRecognizer:
GestureRecognizerFactoryWithHandlers<CustomVerticalMultiDragGestureRecognizer>(
() => CustomVerticalMultiDragGestureRecognizer(debugOwner: null),
(CustomVerticalMultiDragGestureRecognizer instance) {
instance.onStart = (Offset position) {
return CustomDrag(
events: instance.events,
onUpdate: onUpdate,
);
};
},
),
},
child: child,
);
}
}
typedef OnUpdate = Function(DragUpdateDetails details);
class CustomDrag extends Drag {
final List<PointerDownEvent> events;
final OnUpdate onUpdate;
CustomDrag({required this.events, required this.onUpdate});
@override
void update(DragUpdateDetails details) {
super.update(details);
final delta = details.delta;
if (delta.dy.abs() > 0 && events.length == 2) {
onUpdate.call(DragUpdateDetails(
sourceTimeStamp: details.sourceTimeStamp,
delta: Offset(0, delta.dy),
primaryDelta: details.primaryDelta,
globalPosition: details.globalPosition,
localPosition: details.localPosition,
));
}
}
}
class CustomVerticalMultiDragGestureRecognizer extends MultiDragGestureRecognizer {
final List<PointerDownEvent> events = [];
CustomVerticalMultiDragGestureRecognizer({required Object? debugOwner}) : super(debugOwner: debugOwner);
@override
createNewPointerState(PointerDownEvent event) {
events.add(event);
return _CustomVerticalPointerState(event.position, onDisposeState: () {
events.remove(event);
});
}
@override
String get debugDescription => 'custom vertical multi drag';
}
typedef OnDisposeState = Function();
class _CustomVerticalPointerState extends MultiDragPointerState {
final OnDisposeState onDisposeState;
_CustomVerticalPointerState(Offset initialPosition, {required this.onDisposeState})
: super(initialPosition, PointerDeviceKind.touch, null);
@override
void checkForResolutionAfterMove() {
if (pendingDelta!.dy.abs() > kTouchSlop) {
resolve(GestureDisposition.accepted);
}
}
@override
void accepted(GestureMultiDragStartCallback starter) {
starter(initialPosition);
}
@override
void dispose() {
onDisposeState.call();
super.dispose();
}
}
@Lukas-io
Copy link

Lukas-io commented May 3, 2024

thanks man

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment