How to use inner touch coordinate with Draggable - flutter

Here is an example of using Draggable.
Is there a possibility to get also like the touch coordinate within the Draggable widget? I illustrated what I'm searching for in the image with x1 and x2.
So I want to determine one of the inner coordinates like x1 or x2.
Here is how I use draggable so far.
draggable = new Draggable(
data: widget.text,
feedback: avatar,
child: item,
onDraggableCanceled: (velocity, offset) {
// the inner touch point is not included in offset ...
},
);
Draggable docs
If it doesn't work with Draggable. Is there an alternative which I can use?

You can wrap your draggable widget in a Listener and you can do the below code.
onPointerDown: (PointerEvent event) {
print("Touch Position Of your Widget ${event.position}");
},

Related

How to absorb swipe motion only in 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

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.

Drag an image on top of another image with Flutter

I want to drag an image on top of another image at any position. The problem is that Draggable Widget returns the Widget back to initial position after I release the touch, also Drag Target only accepts one fixed position. Any idea?
Thanks
You can use the onAccept parameter of the Draggable widget & update the offset value of the widget that's passed to your function as an argument:
Draggable(
offset: Offset(xFromState, yFromState)
onAccept: (value) {
// Do something with the DragTarget value here
}
)

Flutter: How to make a ListView transparent to pointer events (but not its non-transparent contents)?

I have a Scrollable (ListView or any other) and it contains a transparent widget, say Container(height:200). I can see through both the widget and the scrollable (in other words I can see the widgets behind the scrollable).
How can I be able to click through the transparent widget and the scrollable, so that I reach the widgets behind the scrollable?
ListView(
children: [
Container(height: 200), // Transparent.
Container(color: Colors.red, height: 200),
],
);
Note, I cannot wrap the scrollable with IgnorePointer, because I still want to click the non-transparent widgets in the scrollable.
The only reasonable solution I can think of is to have a GestureDetector on the transparent container, which will give you the global position of the taps:
GestureDetector(
onTapUp: (TapUpDetails tapUpDetails) {
print("onTapUp global: " + tapUpDetails.globalPosition.toString());
},
And then add a Key to the widget behind the list, and use it to get the global position of the top left corner of the widget's rectangle, as well as the size of the widget, and use those to get the rectangle of the widget:
RenderBox renderBox = _key.currentContext.findRenderObject();
Offset topLeftCorner = renderBox.localToGlobal(Offset.zero);
Size size = renderBox.size;
Rect rectangle = topLeftCorner & size;
If the background widget does not move, you can do it within initState on the very next frame using WidgetsBinding.instance.addPostFrameCallback (the render object will be null if do it synchronously within initState) and save the Rect - otherwise you will have to recalculate it on every tap.
And then finally on each tap on the transparent container you can calculate whether the tap's position is within the boundaries of the background widget, and invoke the corresponding code:
// if tap is within boundaries of the background widget
if (rectangle.contains(tapUpDetails.globalPosition)) {
// your code here
}

How to get the touch position while dragging

I would like to get the touch position while dragging and perform a setState(position). (In Android: getTouchPositionFromDragEvent). I can't find anything that I could use in the Draggable class but maybe there is a work around?
You should use GestureDetector for that:
for example:
GestureDetector(
onVerticalDragDown: (DragDownDetails details) {
print(details.globalPosition);
},
child: // ...
)
see https://docs.flutter.io/flutter/widgets/GestureDetector-class.html
for more detail.
Or you could use a Listener to get raw data Pointer position.
Listener(
onPointerDown: (PointerDownEvent event) {
print(event.position);
},
child: // ...
)
See https://flutter.io/gestures/ to have a comparison between Listener and GestureDetector.