Flutter 组件分析之Draggable
引语
Draggable 是 flutter 中随手试拖动的一个控件。既然它可以支持多点触碰并且同时可以支持拖拽,那么不由猜想是不是由点击事件获取锚点随后创建 overlay ,但是事实真的是这样吗?让我们深入源码来看看官方给出的答案!
Draggable
简单看一下 Draggable 的传参
1 | const Draggable({ |
实际上比较需要关注的是 feedback 这个参数。因为它是触碰组件后产生的浮层,其余的参数都是为这个参数作的一些调整。Draggable 由于是一个 StatefulWidget ,我们可以从其 state 的 build 周期了解下具体它的布局结构 从而进一步判断它做了什么。
1 | @override |
build() 方法中 ,仅返回 Listener widget ,猜测手势的真正的处理应该在 _routerPointer() 中实现的,那么routerPointe()做了一些什么呢?让我们抽丝剥茧,进一步了解康康。_recognizer.addPointer(event)中,_recognizer实际上是一个GestureRecognizer对象,那么它添加的pointer也就是对手势识别的处理。我们可以看一下他的手势识别是在哪里注册的。跟进源码,
1 | void _routePointer(PointerDownEvent event) { |
发现在 initState() 中 recognizer 通过 widget.createRecognize(_startDrag) 注册了手势滑动事件。createRecognize()内部处理了真正的去响应事件手势。因此可以判断startDrag()内部生成了浮层,每次触碰widget都会传递Pointerdown事件,在_recognizer这里作手势识别,最终相应绘制。
那么startDrag()内部怎么实现的呢?
1
2
3
4
5
6
7
8
9switch (widget.dragAnchor) {
case DragAnchor.child:
final RenderBox renderObject = context.findRenderObject() as RenderBox;
dragStartPoint = renderObject.globalToLocal(position);
break;
case DragAnchor.pointer:
dragStartPoint = Offset.zero;
break;
}
首先通过 DragAnchor 获取锚点的位置。值得注意的是,renderObject.globalToLocal(position) 获取的锚点是以手机左上角为原点 到widget左上角的坐标。
随后便创建了一个_DragAvatard对象 这个对象的内部!注意~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20_DragAvatar({
@required this.overlayState,
this.data,
this.axis,
Offset initialPosition,
this.dragStartPoint = Offset.zero,
this.feedback,
this.feedbackOffset = Offset.zero,
this.onDragEnd,
@required this.ignoringFeedbackSemantics,
}) : assert(overlayState != null),
assert(ignoringFeedbackSemantics != null),
assert(dragStartPoint != null),
assert(feedbackOffset != null) {
// 说明依然是一个overlay的对象
_entry = OverlayEntry(builder: _build);
overlayState.insert(_entry);
_position = initialPosition;
updateDrag(initialPosition);
}
至此引发对手势识别器的思考,
可以通过对手势识别的监听去做一些手势上拦截或者亲和性的操作。可以更细化的手势滑动方面做处理
这里是WeninerIo😇
如果你对这次的技术分享感兴趣或者有什么疑惑🧐
不妨在评论区留言或私信🤪
或许这次的分享不是你所期待的😣
那就点个关注吧! 🙏
下次也许就是你中意的呢🫣?