Flutter中如何判断鼠标从Widget的哪一侧离开?
Flutter中判断鼠标从Widget哪一侧离开的实现方式
当然有简便的实现方式,核心思路是在鼠标离开时,获取其相对于目标Widget的本地坐标,再结合Widget的尺寸边界,计算鼠标位置到各边的距离,距离最短的一侧就是离开方向。
具体实现代码
可以封装一个可复用的DirectionalMouseRegion组件,内部通过MouseRegion监听事件并处理方向判断:
import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; class DirectionalMouseRegion extends StatefulWidget { final Widget child; final void Function(String direction) onExitDirection; const DirectionalMouseRegion({ super.key, required this.child, required this.onExitDirection, }); @override State<DirectionalMouseRegion> createState() => _DirectionalMouseRegionState(); } class _DirectionalMouseRegionState extends State<DirectionalMouseRegion> { RenderBox? _renderBox; @override void initState() { super.initState(); // 等待Widget渲染完成后获取RenderBox WidgetsBinding.instance.addPostFrameCallback((_) { _renderBox = context.findRenderObject() as RenderBox; }); } String _getExitDirection(PointerExitEvent event) { if (_renderBox == null) return 'unknown'; final localPosition = _renderBox!.globalToLocal(event.position); final size = _renderBox!.size; // 计算鼠标位置到Widget各边的距离 final distanceToLeft = localPosition.dx; final distanceToRight = size.width - localPosition.dx; final distanceToTop = localPosition.dy; final distanceToBottom = size.height - localPosition.dy; // 找出距离最短的边 final minDistance = [distanceToLeft, distanceToRight, distanceToTop, distanceToBottom].reduce((a, b) => a < b ? a : b); if (minDistance == distanceToLeft) return 'left'; if (minDistance == distanceToRight) return 'right'; if (minDistance == distanceToTop) return 'top'; return 'bottom'; } @override Widget build(BuildContext context) { return MouseRegion( onExit: (event) { final direction = _getExitDirection(event); widget.onExitDirection(direction); }, child: widget.child, ); } }
使用示例
直接将需要监听的Widget作为子组件传入,即可获取离开方向:
DirectionalMouseRegion( onExitDirection: (direction) { print('鼠标从$direction侧离开'); }, child: Container( width: 200, height: 200, color: Colors.lightBlueAccent, alignment: Alignment.center, child: const Text('Hover me'), ), )
注意事项
- 必须等待Widget渲染完成后才能获取
RenderBox,否则无法正确计算坐标和尺寸,这里用addPostFrameCallback确保时机正确。 - 如果Widget尺寸会动态变化(比如响应式布局),可以在
didUpdateWidget或添加SizeChangedLayoutNotifier来更新_renderBox的引用,保证判断准确。 - 这种基于距离判断的方式逻辑简单,适用于绝大多数常规场景,不需要依赖额外第三方库。
内容的提问来源于stack exchange,提问作者SdtElectronics
相关产品推荐
相关产品推荐

