Issue
How can i create a movable/draggable widget in flutter that stays at the position it is dragged to .I tried using draggable widget but the widget which gets wrapped in draggable returns back to the original position after releasing the the drag.
Solution
On top of dragging the object around, you can also make it zoomable with the help of a GestureDetector
. I applied the GestureDetector
to the main Stack so that you can pinch to zoom in/out anywhere on the screen. It makes it somewhat easier to see what you are doing.
HookWidget version
class DragArea extends HookWidget {
final Widget child;
const DragArea({Key key, this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
final position = useState(Offset(100, 100));
final prevScale = useState(1.0);
final scale = useState(1.0);
return GestureDetector(
onScaleUpdate: (details) => scale.value = prevScale.value * details.scale,
onScaleEnd: (_) => prevScale.value = scale.value,
child: Stack(
children: [
Positioned.fill(
child: Container(color: Colors.amber.withOpacity(.4))),
Positioned(
left: position.value.dx,
top: position.value.dy,
child: Draggable(
maxSimultaneousDrags: 1,
feedback: Transform.scale(
scale: scale.value,
child: child,
),
childWhenDragging: Opacity(
opacity: .3,
child: Transform.scale(
scale: scale.value,
child: child,
),
),
onDragEnd: (details) => position.value = details.offset,
child: Transform.scale(
scale: scale.value,
child: child,
),
),
)
],
),
);
}
}
StatefulWidget version
class StatefulDragArea extends StatefulWidget {
final Widget child;
const StatefulDragArea({Key key, this.child}) : super(key: key);
@override
_DragAreaStateStateful createState() => _DragAreaStateStateful();
}
class _DragAreaStateStateful extends State<StatefulDragArea> {
Offset position = Offset(100, 100);
double prevScale = 1;
double scale = 1;
void updateScale(double zoom) => setState(() => scale = prevScale * zoom);
void commitScale() => setState(() => prevScale = scale);
void updatePosition(Offset newPosition) =>
setState(() => position = newPosition);
@override
Widget build(BuildContext context) {
return GestureDetector(
onScaleUpdate: (details) => updateScale(details.scale),
onScaleEnd: (_) => commitScale(),
child: Stack(
children: [
Positioned.fill(
child: Container(color: Colors.amber.withOpacity(.4))),
Positioned(
left: position.dx,
top: position.dy,
child: Draggable(
maxSimultaneousDrags: 1,
feedback: widget.child,
childWhenDragging: Opacity(
opacity: .3,
child: widget.child,
),
onDragEnd: (details) => updatePosition(details.offset),
child: Transform.scale(
scale: scale,
child: widget.child,
),
),
),
],
),
);
}
}
Answered By - Thierry
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.