flutter 自定义拖砖 吸附组件

5 阅读1分钟
double leftPosition = 0.0; // 初始位置
double topPosition = 40.0; // 初始位置

添加一个 `GlobalKey`,用于 Stack 获取其在屏幕上的位置
final GlobalKey _stackKey = GlobalKey();

// 吸附区域的距离
final double snapDistance = 50.0;


 Stack(
  key: _stackKey,
  children: [
    SafeArea(
      child: Text(‘1111111’)
            ),
          ],
        ),
      ),
    ),
    Positioned(
      left: leftPosition,
      top: topPosition,
      child: Draggable(
        feedback: Container(
          width: 50,
          height: 50,
          decoration: BoxDecoration(
            shape: BoxShape.circle,
            color: Colors.blue.withOpacity(0.5),
          ),
        ),
        childWhenDragging: Container(),
        child: Container(
          width: 50,
          height: 50,
          decoration: BoxDecoration(
            shape: BoxShape.circle,
            color: Colors.blue,
          ),
        ),
        onDragUpdate: (details) {
          setState(() {
            RenderBox? stackRenderBox =
                _stackKey.currentContext?.findRenderObject()
                    as RenderBox?;
            if (stackRenderBox == null) return;

            Offset stackLocalOffset = stackRenderBox.globalToLocal(
              details.globalPosition,
            );
            
            leftPosition = stackLocalOffset.dx - 25; 
            topPosition = stackLocalOffset.dy - 25; 
            double stackWidth = stackRenderBox.size.width;
            
            if (leftPosition < snapDistance) {
              leftPosition = 0; 
            } else if (leftPosition > stackWidth - snapDistance - 50) {
              leftPosition = stackWidth - 50;
            }
            double stackHeight = stackRenderBox.size.height;
            topPosition = topPosition.clamp(0.0, stackHeight - 50);
          });
        },
        onDraggableCanceled: (velocity, offset) {
          setState(() {
            RenderBox? stackRenderBox =          _stackKey.currentContext?.findRenderObject() as RenderBox?;
            if (stackRenderBox == null) return;
            double stackWidth = stackRenderBox.size.width;
            double centerWidth = stackWidth / 2; 
            double currentCenterX =leftPosition + 25; 
            if (currentCenterX < centerWidth) {
              leftPosition = 0;
            } else {
              leftPosition = stackWidth - 50;
            }
          });
        },
      ),
    ),
  ],
),