UME: 对齐标尺
功能查看
今天来看看对其标尺是怎么实现的, 先来看看该功能是什么样的
可以当道当我们移动红色区域时,上方的坐标信息也会实时显示,当我们打开自动吸附功能时,手势移动停止时,他就会自动吸附在当前widget的最近角点上
看到这个功能我们先来盲猜一下是怎么实现的,然后再来看源码的实现,首先红色区域上是一定有个手势控制移动的, 当停止时,来获取点的坐标, 然后通过坐标来获取widget, 是不是跟我们前几天看的获取widget信息有点像, 只不过是把点击获取信息改成了手势控制,下面我们就来看看跟我们的猜想是不是一样的
源码查看
今天的代码是在flutter_ume_kit_ui包中,有个align_ruluer.dart,
UI代码主要都在build中,就不看了,看一下手势相关代码
其中有两个手势,一个是toolbar的手势,就是显示位置信息部分,该手势,只改变toolbar的Y值,也就是只能控制该widget的上下移动,也比较简单
void _toolBarPanUpdate(DragUpdateDetails dragDetails) {
setState(() {
_toolBarY = dragDetails.globalPosition.dy - 40;
});
}
再看下另一个手势,这个手势就是红色区域的手势,当没有打开自动吸附功能时,我们可以不用关注onPanEnd方法,在onPanUpdate中也只有一个更新位置的方法,这时候当前页面上需要的尺寸信息都可以计算出来了
GestureDetector(
onPanUpdate: _onPanUpdate,
onPanEnd: _onPanEnd
)
void _onPanUpdate(DragUpdateDetails dragDetails) {
setState(() {
_dotPosition = dragDetails.globalPosition;
});
}
下面我们再看下当开启了自动吸附时的代码,又看到了我们的老朋友HitTest类,还记得widget信息是怎么获取的么,也是通过它拿到的,这时我们拿到了widgetlist后进行遍历找到离我们点击位置最近的角点,进行更新,最后添加了一个震动反馈
void _onPanEnd(DragEndDetails dragDetails) {
if (!_switched) return;
final List<RenderObject> objects = HitTest.hitTest(_dotPosition);
_selection.candidates = objects;
Offset offset = Offset.zero;
for (var obj in objects) {
var translation = obj.getTransformTo(null).getTranslation();
Rect rect = obj.paintBounds.shift(Offset(translation.x, translation.y));
if (rect.contains(_dotPosition)) {
double dx, dy = 0.0;
double perW = rect.width / 2;
double perH = rect.height / 2;
if (_dotPosition.dx <= perW + translation.x) {
dx = translation.x;
} else {
dx = translation.x + rect.width;
}
if (_dotPosition.dy <= translation.y + perH) {
dy = translation.y;
} else {
dy = translation.y + rect.height;
}
offset = Offset(dx, dy);
break;
}
}
setState(() {
_dotPosition = offset == Offset.zero ? _dotPosition : offset;
HapticFeedback.mediumImpact();
});
}
好了今天的源码查看就到这了, 作为Flutter届的一个小学生,希望大家多多指教,有问题的地方一起讨论
转载自:https://juejin.cn/post/7027402881724596238