概述
Flutter手势操作 —全局坐标与局部坐标的获取
全局坐标与局部坐标
在GestureDetector中有两个重要属性值globalPosition和localPosition,两者都是Offset对象。
globalPosition就像它的命名表示当前手势触点在**全局坐标系位置
与对应组件顶点坐标的偏移量(dx,dy)
;
localPosition则就表示当前手势触点在对应组件坐标系位置
与对应组件顶点坐标的偏移量(dx,dy)
**。
例如如下代码中,为Container设置了GestureDetector手势监听,在update回调中获取updateDetail对象,在Text中显示globalPosition偏移量。从中获取到的globalPosition和localPosition中dx的值相同,dy却不同。也就是因为Scaffold中设置了AppBar,相对于body他的全局坐标系并非它自身。但若将Scaffold中的AppBar去除,让body撑满整个Scaffold,那么在手势监听中获取到的globalPosition和localPosition偏移量将相同。
需要注意的是对于globalPosition在安卓中还包含了手机状态栏的高度。
通过DragUpdateDetails获取全局坐标和局部坐标
DragUpdateDetails 相当网页前端的Evnet事件,可以获取当前触摸点的全局坐标和局部坐标。
onPanUpdate: (DragUpdateDetails detail) {
//获取当前触摸点的全局坐标
var globalPosition=detail.globalPosition;
//获取当前触摸点的局部坐标
var localPosition=detail.localPosition;
}
通过contexnt.findRenderObject()获取全局坐标和局部坐标
当前的页面结构(PainterPage):
-
Scafford
-
body
- GestureDetector //手势Widget
- onPanUpdate(detail)
- GestureDetector //手势Widget
-
onPanUpdate:(detail){
final RenderBox Box = context.findRenderObject();
// 获取的对象为当前页面对象,PainterPage
Offset localPosition = Box.globalToLocal(detail.globalPosition);
// 转换为局部坐标但实际是全局坐标
Offset globalPosition = Box.localToGlobal(detail.globalPosition);
// 获得的是全局坐标。
}
为甚么通过这样的方式,不能正确获取到局部坐标呢?
原因在于context.findRenderObject()
,通过context
,获取到的Box,实际上是PaintPage本身。所以,对于Box自身来说全局坐标
和局部坐标
是一致的。
而实际上我们真正想要的是GestureDetector里的坐标系。由前面我们可以知道context.findRenderObject()
只能获取context
当前所在页面的页面 Widget
。
为了解决不能获取到GuesterDetector
的坐标的问题,我们需要将GuesterDetector
封装成一个StatefulWidget或者一个StatelessWidget,即GuesterDetectorWidget
。再将GuesterDetectorWidget
引入到PainterPage
。
更详细的说明可以参详字母索引快速定位
onPanUpdate:(detail){
final RenderBox Box = context.findRenderObject();
// 获取的对象为当前页面对象,PainterPage
Offset localPosition = Box.globalToLocal(detail.globalPosition);
// 转换为局部坐标
Offset globalPosition = Box.localToGlobal(detail.globalPosition);
// 获得的是全局坐标。
}
MaterialApp(
theme: AppTheme.themes[store.state.appThemeState.themeType],
home: Scaffold(
appBar: AppBar(),
body: GestureDetector(
onPanStart: (detail) {
showLog(detail.runtimeType, detail.localPosition,
detail.globalPosition);
},
onPanUpdate: (detail) {
showLog(detail.runtimeType, detail.localPosition,
detail.globalPosition);
setState(() {
offsetText = "globalPosition: ${Offset(detail.globalPosition.dx, detail.globalPosition.dy).toString()} n"
"localPosition: ${Offset(detail.localPosition.dx, detail.localPosition.dy).toString()}";
});
},
onPanEnd: (detail) {
setState(() {
offsetText = "end";
});
},
child: Container(
color: Colors.red,
width: double.infinity,
height: double.infinity,
child: Center(
child: Text(
offsetText,
style: TextStyle(
color: Colors.white,
fontSize: 25,
),
),
),
),
),
),
);
可以看到当Scaffold包含和未包含AppBar时,Container两个偏移量输出的差异。
-
Flutter的坐标体系是以Widget的左上角为原点,向左为正x轴,以下为正y轴;
-
全局坐标是整个屏幕的左上角开始计算的
-
局部坐标,是以当前GestureDetector包裹的Wiget的左上角为原点开始计算的
参考资料:
Flutter实战之手势操作篇
实现 View 的移动拖拽
flutter 白板工具
最后
以上就是冷酷大侠为你收集整理的Flutter手势操作 ---全局坐标与局部坐标的获取Flutter手势操作 —全局坐标与局部坐标的获取的全部内容,希望文章能够帮你解决Flutter手势操作 ---全局坐标与局部坐标的获取Flutter手势操作 —全局坐标与局部坐标的获取所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复