限制定位小部件的堆栈区域

Constrain stack area for Positioned widget

我有一个可拖动的 Positioned 小部件,通过使用 Offset 并将其包裹在 Gesture Detector 中以更新其位置,我想限制此小部件可以移动的区域,因此它不能超出边界。结构是这样的:

如下图,我希望圆只在灰线内移动。可能吗?

提供 2x 值作为限制,我这样做是为了触摸位置。 此外,dx 和 dy 轴都可以单独工作。如果你不想要它,你可以在一个 setState 上组合两个条件。

结果

小部件

class HomeWidget extends StatefulWidget {
  @override
  _HomeWidgetState createState() => _HomeWidgetState();
}

class _HomeWidgetState extends State<HomeWidget> {
  double dx = 0;
  double dy = 0;

  get limit => 50;
  get containerSize => 50;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LayoutBuilder(
        builder: (context, constraints) => Stack(
          children: [
            Positioned(
              left: limit * .5,
              child: Container(
                height: constraints.maxHeight,
                width: 5,
                color: Colors.grey,
              ),
            ),
            Positioned(
              bottom: limit * .5,
              child: Container(
                width: constraints.maxWidth,
                height: 5,
                color: Colors.grey,
              ),
            ),
            Positioned(
              top: dy - containerSize * .5,
              left: dx - containerSize * .5,
              child: Container(
                height: containerSize,
                width: containerSize,
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: Colors.deepPurple,
                ),
              ),
            ),
            GestureDetector(
              onPanUpdate: (details) {
                if (details.localPosition.dx > limit)
                  setState(() {
                    dx = details.localPosition.dx;
                  });
                if (details.localPosition.dy < constraints.maxHeight - limit)
                  setState(() {
                    dy = details.localPosition.dy;
                  });

                print(" $dx, $dy ");
              },
            ),
          ],
        ),
      ),
    );
  }
}