Flutter判断点击坐标是否在widget范围内

803 阅读1分钟
  1. 为该Widget指定GlobalKey:

2、在GestureDetector的onTap回调中获取点击坐标和Widget的RenderBox:

GestureDetector(
  onTap: (TapDownDetails details) {
    final RenderBox box = key.currentContext!.findRenderObject() as RenderBox;
    final Offset tapPos = details.localPosition;  // 点击的坐标
  }   
) 

3、从RenderBox获取Widget的位置offset和大小size信息:

final Size size = box.size;  
final Offset offset = box.localToGlobal(Offset.zero);

4、利用tapPos、offset和size判断点击是否在Widget范围内:

if (tapPos.dx > offset.dx && 
    tapPos.dx < offset.dx + size.width &&
    tapPos.dy > offset.dy &&
    tapPos.dy < offset.dy + size.height) {
  print('点击在Widget内!');  
} else {
  print('点击不在Widget内!');
}

示例代码:

class MyWidget extends StatefulWidget {
  MyWidget({Key? key}) : super(key: key);
  
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  final GlobalKey<MyWidgetState> key = GlobalKey();
  
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: (TapDownDetails details) {
        final RenderBox box = key.currentContext!.findRenderObject() as RenderBox;
        final Offset tapPos = details.localPosition;
        final Size size = box.size;
        final Offset offset = box.localToGlobal(Offset.zero); 
        
        if (tapPos.dx > offset.dx && 
            tapPos.dx < offset.dx + size.width &&
            tapPos.dy > offset.dy &&
            tapPos.dy < offset.dy + size.height) {
          print('点击在Widget内!');  
        } else {
          print('点击不在Widget内!');
        }
      },
      child: MyWidget(key: key)
    );
  }
}