MouseRegion 是 Flutter 开发中,在桌面应用与Web应用中,用来监听一定区域内鼠标的进入与退出,以及移动轨迹。
在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天、每周,都会留下一些脚印,就是这些创作的内容,有一种执着,就是不知为什么,如果你迷茫,不妨来瞅瞅码农的轨迹。
如果你有兴趣 你可以关注一下公众号 biglead 来获取最新的学习资料。
先来看看本文章实现的效果
直接来看代码吧
首先是启动函数
main() {
runApp(MaterialApp(
//不显示 debug标签
debugShowCheckedModeBanner: false,
//显示的首页面
home: DemoMouseRegionPage(),
));
}
然后是定义我这个首页面了 DemoMouseRegionPage
///代码清单
class DemoMouseRegionPage extends StatefulWidget {
@override
_DemoMouseRegionPageState createState() => _DemoMouseRegionPageState();
}
class _DemoMouseRegionPageState extends State<DemoMouseRegionPage> {
//为true时鼠标进入了监听区域中
bool _isEnter = false;
//绑定文本框,用来获取文本Text的位置与大小信息
GlobalKey _globalKey = GlobalKey();
//文本颜色
Color _textColor = Colors.black;
@override
Widget build(BuildContext context) {
//
return Scaffold(
appBar: AppBar(
title: Text("MouseRegion"),
),
body: Container(
width: double.infinity,
padding: EdgeInsets.all(10),
child: Column(
children: [
//鼠标事件监听
buildMouseRegion(),
],
),
),
);
}
我将 MouseRegion 组件通过 函数封装的形式来构建 ,代码如下:
MouseRegion buildMouseRegion() {
return MouseRegion(
//进入
onEnter: (PointerEnterEvent event) {
print("进入 ---");
setState(() {
_isEnter = true;
});
},
//退出
onExit: (PointerExitEvent event) {
print("退出 ---");
setState(() {
_isEnter = false;
});
},
onHover: (PointerHoverEvent event) {
//x 当前鼠标位置
buildHoverEvent(event);
},
child: Container(
width: double.infinity,
alignment: Alignment.center,
height: 300,
child: Text(
"这是什么 ???",
key: _globalKey,
style: TextStyle(color: _textColor),
),
color: _isEnter ? Colors.blueAccent : Colors.blue[200],
),
);
}
在这里是通过 _isEnter 来记录鼠标是否进入到了 MouseRegion 监听的范围内,同样的是根据 _isEnter 的变化 来动态修改 Container 的背景颜色的。
然后在 鼠标移动监听的回调 onHover 中,通过 PointerHoverEvent 参数来实时获取了 鼠标的位置 ,通过 Text 绑定的 GlobalKey 来获取 Text 组件的位置与大小 ,从而来计算 鼠标是否在 Text 的区域内。
void buildHoverEvent(PointerHoverEvent event) {
//x 当前鼠标位置
double x = event.position.dx;
double y = event.position.dy;
//获取文本组件的属性信息
RenderBox renderBox = _globalKey.currentContext.findRenderObject();
//文本组件的左上角点坐标
Offset offset = renderBox.localToGlobal(Offset.zero);
double topX = offset.dx;
double topY = offset.dy;
//文本组件的大小
Size size = renderBox.paintBounds.size;
//文本组件的右下角点坐标
double bottomX = topX + size.width;
double bottomY = topY + size.height;
if (x > topX && x < bottomX && y > topY && y < bottomY) {
//在文本组件 Text 的区域内 文字颜色为红色
_textColor = Colors.red;
} else {
_textColor = Colors.black;
}
setState(() {});
print("onHover --- $x $y $offset");
}
完毕