Open ibrahimEltayfe opened 5 months ago
I have the same problem. In my case I'm dragging a chip with some label:
feedback
appears misplaced in both directions and offset of this misplacement changes on moving.
No big difference with the code above - Chip
as a child of draggable and the same chip as feedback and no onDragCallbacks.
@rayliverified Could you please help us to resolve this?
@ibrahimEltayfe Thank you very much for sharing your solution!
Dunno why, but it my case it doesn't work - feedback is still misplaced. But I made a workaround this way:
dragAnchorStrategy: (final draggable, final context, final position) {
final responsiveBreakpoints = ResponsiveBreakpoints.of(context);
final mediaQuery = MediaQuery.of(context);
final double widthOffset =
mediaQuery.size.width - responsiveBreakpoints.screenWidth;
final double heightOffset =
mediaQuery.size.height - responsiveBreakpoints.screenHeight;
final RenderBox renderObject = context.findRenderObject()! as RenderBox;
return renderObject.globalToLocal(
Offset(
position.dx - widthOffset / 2,
position.dy - heightOffset / 2,
),
);
},
It's not quite proper, I think, but better, than nothing. And when you are moving your feedback widgets, it's sliding from your finger a little bit (further you move, more it slides).
Maybe it'll be a good idea to leave a report in flutter issues too.
@abigotado
Nice, your solution worked fine like this:
Offset adjustPosition(BuildContext context, Offset position){
final RenderBox? renderObject = context.findRenderObject() as RenderBox?;
return renderObject?.globalToLocal(
Offset(
position.dx,
position.dy,
),
) ?? position;
}
without any further calculations, because globalToLocal is converting the global position (coordinates relative to the entire screen) to the coordinates relative to the widget itself. This takes into account any transformations or scaling applied to the widget's layout.
class _HomeState extends State<_Home> {
Offset position = const Offset(0, 0);
Offset currentPos = const Offset(0, 0);
void _onDragUpdate(BuildContext context, DragUpdateDetails details) {
currentPos += details.delta;
}
void _onDragEnd(BuildContext context, DraggableDetails details) {
setState(() {
position = adjustPosition(context, currentPos);
});
}
Offset adjustPosition(BuildContext context, Offset position){
final RenderBox? renderObject = context.findRenderObject() as RenderBox?;
return renderObject?.globalToLocal(position,) ?? position;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Positioned(
top: position.dy,
left: position.dx,
child: Draggable(
onDragUpdate: (details) => _onDragUpdate(context, details),
onDragEnd: (details) => _onDragEnd(context, details),
childWhenDragging: const SizedBox.shrink(),
feedback: const Material(child: Text("DRAGGABLE",style: TextStyle(fontSize: 50),)),
child: const Text("DRAGGABLE",style: TextStyle(fontSize: 50),),
),
),
]
),
),
);
}
}
The feedback positioning is working fine without handling its offset, I do not know why the feedback position not working properly on your side, my problem was with placing the item on the scaled screen. but the coordinates coming from the DraggableDetails are fine.
My remaining problem is the scale of the feedback item, I will try to make a calculation for the scale.
@ibrahimEltayfe Well, I have some suggestions about the difference. Do you place ResponsiveScaledBox
at home
parameter of MaterialApp
? In my case I use builder
. And when I move it to home - I see the same behavior as you describe - wrong scale. And when return it to builder
- it has wrong position. Flutter team has confirmed the problem, see here: https://github.com/flutter/flutter/issues/146002
@ibrahimEltayfe
Your solution for the position works great. Did you find the solution for the scale issue?
@abigotado
Nice, your solution worked fine like this:
Offset adjustPosition(BuildContext context, Offset position){ final RenderBox? renderObject = context.findRenderObject() as RenderBox?; return renderObject?.globalToLocal( Offset( position.dx, position.dy, ), ) ?? position; }
without any further calculations, because globalToLocal is converting the global position (coordinates relative to the entire screen) to the coordinates relative to the widget itself. This takes into account any transformations or scaling applied to the widget's layout.
class _HomeState extends State<_Home> { Offset position = const Offset(0, 0); Offset currentPos = const Offset(0, 0); void _onDragUpdate(BuildContext context, DragUpdateDetails details) { currentPos += details.delta; } void _onDragEnd(BuildContext context, DraggableDetails details) { setState(() { position = adjustPosition(context, currentPos); }); } Offset adjustPosition(BuildContext context, Offset position){ final RenderBox? renderObject = context.findRenderObject() as RenderBox?; return renderObject?.globalToLocal(position,) ?? position; } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Stack( children: [ Positioned( top: position.dy, left: position.dx, child: Draggable( onDragUpdate: (details) => _onDragUpdate(context, details), onDragEnd: (details) => _onDragEnd(context, details), childWhenDragging: const SizedBox.shrink(), feedback: const Material(child: Text("DRAGGABLE",style: TextStyle(fontSize: 50),)), child: const Text("DRAGGABLE",style: TextStyle(fontSize: 50),), ), ), ] ), ), ); } }
The feedback positioning is working fine without handling its offset, I do not know why the feedback position not working properly on your side, my problem was with placing the item on the scaled screen. but the coordinates coming from the DraggableDetails are fine.
My remaining problem is the scale of the feedback item, I will try to make a calculation for the scale.
Screen.Recording.2024-04-01.at.7.58.29.AM.mov
When using the draggable widget or any other widget that uses offset, the positioning appears to be skewed or displaced. it does not retain its intended positions accurately during the interaction, resulting in an inaccurate rendering of the UI.
https://github.com/Codelessly/ResponsiveFramework/assets/40795940/58e294f4-60e2-4ff9-9c8d-e95ef4a53fc0
https://github.com/Codelessly/ResponsiveFramework/assets/40795940/cc049c98-6bac-43f6-b7f2-52d090a6f85b
Here is the code:
Flutter (Channel stable, 3.19.3)