如何在 flutter 中创建一个可移动的小部件,使其保持在拖动到的位置

X10*_*000 9 draggable flutter flutter-layout

我如何在 flutter 中创建一个可移动/可拖动的小部件,使其保持在拖动到的位置。我尝试使用可拖动的小部件,但包裹在可拖动的小部件在释放拖动后返回到原始位置。

正如您在此 GIF 中看到的,可拖动对象返回到其原始位置。如何让它留在那里

Thi*_*rry 16

除了四处拖动对象之外,您还可以借助 使其可缩放GestureDetector。我将 应用于GestureDetector主堆栈,以便您可以在屏幕上的任何位置进行捏合放大/缩小。它使您更容易看到自己在做什么。

在此输入图像描述


HookWidget版本

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,
              ),
            ),
          )
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

StatefulWidget版本

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,
              ),
            ),
          ),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)