How to absorb swipe motion only in Flutter - flutter

I am looking for a widget, analogous to AbsorbPointer, that would absorb swipe motions. The goal is to allow "tap" actions to go through to the child but let the parent handle the "swipe" motions.
If possible I would like to also differentiate absorption depending on direction (only absorb vertical motion for example).
Thank you for your help,

you can use GestureDetector to detect tap behavior and swipe motions
GestureDetector(
child: Widget(), // your widget
onTap: () { // Tap behavior listener
// your tap logic
},
onHorizontalDragUpdate: (DragUpdateDetails details) { // Swipe behavior listener
print(details.primaryDelta); // Positive is left to right, Negative is right to left
// your swipe logic
},
)
using two GestureDetector you can warp the parent with listener onHorizontalDragUpdate to detect the swipe motion while warping the child with listener onTap to detect the tap behavior

Related

Flutter GestureDetector onTapRight & ontapLeft

i have read the flutter documentation about GestureDetector and i can only see onTapDown &
onTapUp
and i believe if there is up and Down there will be Right and Left
how can i achieve onTapRight and onTapLeft
onTapDown & onTapUp do not refer to the area/position where you press, but they do refer to:
onTapDown: The moment your finger actually touch the screen
onTapUp: The moment your finger leave the screen
From the docs:
onTapDown: A pointer that might cause a tap with a primary button has contacted the screen at a particular location.
onTapUp: A pointer that will trigger a tap with a primary button has stopped
contacting the screen at a particular location
To achieve right or left tap, you could use a Stack widget to overlay a row with 2 Gesture dector widgets.
DOCS:
onTapDown
GestureTapDownCallback
thanks to #L.Gangemi that gave me the idea of what to use....
i solved this by this sample code
onTapUp: (details) {
if (details.localPosition.direction >
1.0) {
print('Left');
}
if (details.localPosition.direction <
1.0) {
print('Right');
}
},

Using GestureDetector inside InteractiveViewer

Is it possible to use GestureDetector — specifically the onTapUp gesture — inside of an InteractiveViewer?
I know InteractiveViewer uses a GestureDetector itself and overrides the onScaleEnd, onScaleStart, and onScaleUpdate methods to implement panning. However, onTapUp is not overriden, which makes me think there's potential to use it.
I did some digging around and found this in the InteractiveViewer's TransformationController documentation for the toScene() method:
Return the scene point at the given viewport point.
A viewport point is relative to the parent while a scene point is
relative to the child, regardless of transformation. Calling toScene
with a viewport point essentially returns the scene coordinate that
lies underneath the viewport point given the transform.
The viewport transforms as the inverse of the child (i.e. moving the
child left is equivalent to moving the viewport right).
This method is often useful when determining where an event on the
parent occurs on the child. This example shows how to determine where
a tap on the parent occurred on the child.
GestureDetector(
onTapUp: (TapUpDetails details) {
_childWasTappedAt = _transformationController.toScene(
details.localPosition,
);
},
child: InteractiveViewer(
transformationController: _transformationController,
child: child,
), ); }
So it seems that rather than having a GestureDetector as a child, the recommended solution is to wrap the InteractiveViewer with a GestureDetector, use a custom TransformationController, and get the position relative to the viewer viewport from this controller.

How to detect multiple gestures using a single instance of GestureDetector?

I want make WhatsApp voice audio record function. User tap and hold to record audio but can swipe left to cancel. But when I use GestureDetector it only register one gesture type.
For example this only register onLongPress gesture if user start with long press. Or only onHorizontalDrag if user start with horizontal drag:
onLongPressStart: _onPressStart,
onLongPressUp: _onPressEnd,
onHorizontalDragDown: _onHorizontalDragDown,
onHorizontalDragUpdate: _onHorizontalDragUpdate,
onHorizontalDragEnd: _onHorizontalDragEnd,
How to use 2 gesture one after the other?
Thanks!
Try using onLongPressMoveUpdate callback provided by GestureDetector
This provides LongPressMoveUpdateDetails which has a property called offsetFromOrigin.
offsetFromOrigin gives you an Offset object whose dx value is what you need.
GestureDetector(
child: ...
onLongPressMoveUpdate: (updateDetails) {
if (updateDetails.offsetFromOrigin.dx < 0) {
// Handle horizontal drag towards left
}
}
)
Or, if you can't use the above method, checkout this Medium article

Is there a way in Flutter to catch the "start-moving" event in a Dismissible Widget?

I am using the Dismissible widget to be able to remove certain screens/widgets from a flutter app by swiping them up.
What I need to achieve is to blur the image once the user starts swiping/dismissing them but the widget only has the "onDismissed" callback, but does not offer a way to catch the swiping event.
Any alternatives?
You can achieve That using the GestureDetector widget
// This is the sample
GestureDetector(onPanUpdate: (details) {
if (details.delta.dx > 0) {
// swiping in right direction
}
});
You can check there are many events that you can trigger like onHorizontalDragUpdate, and many more you can check out.

Flutter PointerEvent vs OnTap, one works, the other doesn't

I have a stack widget I am trying to create in which:
1. The user touches the widget button triggering a pointerDown event.
2. Pointer down causes a slider type widget to scale from 0 to 100% from behind the button
3. With finger still down, the user drags to select a value on the scale
4. The value is selected by releasing the finger from the screen i.e. pointerUp.
The widget works fine when I use onTap instead of pointerDown in step 1. But when I try to use a pointer down event, the _open method (that manages the scaleUp of the slider) isn't triggered.
I have followed this example almost exactly: https://fireship.io/lessons/flutter-radial-menu-staggered-animations/, but have tried to change the touch event on the floatingActionbuton like this:
Transform.scale(
scale: widget.scale.value,
child: Listener(
onPointerDown: (PointerDownEvent event) {
print('pointer is down');
setState(() {
_open;
});
},
child: FloatingActionButton(child: Icon(Icons.blur_circular), onPressed: () {})),
)
The print part detects and fires the event, but the _open method does not do anything and the menu part does not appear like in the tutorial link.
I am at a loss.
Since the button below the FloatingActionButton also has a listener, The Listener widget doesn't get's the PointerDown event. So to do that you have to change the behaviour to opaque so that both get the events.
Try Something like this:
Listener(
behavior: HitTestBehavior.opaque,
onPointerDown: (PointerDownEvent details){
},
child: ...,
)