如果手势超出Flutter中的容器范围,如何取消手势

时间:2019-03-04 11:20:06

标签: dart flutter gesture

我正在Flutter中实现Drawing App。我指的是this tutorial,但不知何故我被一个

卡住了

issue

简述:如您所见,我有两个容器。一个用于绘图,一个在下方,用于“在上方绘画”。但是要点超出了范围。我希望用户可以在上层容器中进行绘制。所以我的问题是- 如果手势检测超出了特定容器的范围,该如何取消呢?

代码段:

final GestureDetector paintGesture = GestureDetector(
  onPanUpdate: (DragUpdateDetails details) {
    setState(() {
      RenderBox object = context.findRenderObject();
      Offset _localPosition = object.localToGlobal(details.globalPosition);
      _points = new List.from(_points)..add(_localPosition);
    });
  },
  onPanEnd: (DragEndDetails details) {
      _points.add(null);
  },
  child: sketchArea,
);

final Container sketchArea = Container(
  //margin: EdgeInsets.all(1.0),
  //alignment: Alignment.topLeft,
  color: Colors.white,
  child: new CustomPaint(
    painter: new Signature(points: _points),
    size: Size.infinite,
  ),
);

脚手架:

return new Scaffold(
  body: Container(
    child: Column(
      children: <Widget>[
        Expanded(
          child:  paintGesture,
        ),
        Expanded(
          child: Center(
            child: Container(
              child: Text(
                _selectedInput,
                style: TextStyle(
                  color: Colors.black,
                  fontSize: 40.0,
                ),
              ),
            ),
          ),
        ),
      ],
    ),
  ),
);

1 个答案:

答案 0 :(得分:0)

我使用了来自this post的vovohost解决方案来获取我的Container的坐标:

扩展名:

extension GlobalKeyExtension on GlobalKey {
  Rect get globalPaintBounds {
    final renderObject = currentContext?.findRenderObject();
    var translation = renderObject?.getTransformTo(null)?.getTranslation();
    if (translation != null && renderObject.paintBounds != null) {
      return renderObject.paintBounds
          .shift(Offset(translation.x, translation.y));
    } else {
      return null;
    }
  }
}

用法:

final containerKey = GlobalKey();
Rect get containerRect => containerKey.globalPaintBounds;

Container(
  key: containerKey,
  width: 100,
  height: 50,
)

void printWidgetPosition() {
  print('absolute coordinates on screen: ${containerRect}');
}

一旦获得坐标,就必须使用此方法在Offset的范围内返回Container

Offset _offsetInBox(Offset globalOffset) {
  // Y coordinate
  double nearestY = 0;
  if (globalOffset.dy >= containerRect.top &&
      globalOffset.dy <= containerRect.bottom) {
    nearestY = globalOffset.dy;
  } else {
    if ((containerRect.top - globalOffset.dy).abs() >
        (containerRect.bottom - globalOffset.dy).abs()) {
      nearestY = containerRect.bottom;
    } else {
      nearestY = containerRect.top;
    }
  }

  // X coordinate
  double nearestX = 0;
  if (globalOffset.dx >= containerRect.left &&
      globalOffset.dx <= containerRect.right) {
    nearestX = globalOffset.dx;
  } else {
    if ((containerRect.left - globalOffset.dx).abs() >
        (containerRect.right - globalOffset.dx).abs()) {
      nearestX = containerRect.right;
    } else {
      nearestX = containerRect.left;
    }
  }
  print(
      "Global[${globalOffset.dx}, ${globalOffset.dy}], Found=[$nearestX, $nearestY]");

  return Offset(nearestX, nearestY);
}

在您的GestureDetector上,像这样使用它:

final GestureDetector paintGesture = GestureDetector(
  onPanUpdate: (DragUpdateDetails details) {
    setState(() {
      RenderBox renderBox = context.findRenderObject();
      // Use the globalToLocal method if you want the local coordinates, not localToGlobal
      Offset _localPosition = renderBox
                      .globalToLocal(_offsetInBox(details.globalPosition));
      _points = List.from(_points)..add(_localPosition);
    });
  },
  onPanEnd: (DragEndDetails details) {
      _points.add(null);
  },
  child: sketchArea,
);

final Container sketchArea = Container(
  key: containerKey,
  color: Colors.white,
  child: CustomPaint(
    painter: Signature(points: _points),
    size: Size.infinite,
  ),
);