Android源码解读——view与viewGroup的关系

  • 事件的种类和手势
  • view的体系结构和事件分发
  • view和viewgroup的分发流程
  • 解决滑动冲突

 

注:本文只对单点触摸进行处理,多点触摸我们不进行讨论

 

1、事件的种类和手势、了解单点触摸

                      图1

 

 

 

 

2、view的体系结构和事件分发

首先我们需要了解view与viewgroup之间的关系

(1)viewgroup继承了view(从代码角度而言)

(2)viewgroup是view的父亲(从运行时角度而言)

而我们处理嵌套滑动的时候,主要是基于第二点,也就是运行时的角度。

以下两张图就能正确表面,运行时view与viewgroup之间的关系

                        图2

 

                            图3

 

我们通过源码可以得知,事件处理函数主要包括三个:dispatchTouchEvent(事件分发)、onInterceptTouchEvent(事件拦截)、onTouchEvent(事件消费)

下图我们可以清楚的知道,事件分发的流程

                      图4

 

当我们手指触摸到屏幕的时候,activity获取事件,传递给decorview,decorview通过dispatchTouchEvent(事件分发)将事件分发给LinearLayout如图2所示

那么该LinearLayout如果想将事件进行拦截,那么就要执行onInterceptTouchEvent(事件拦截),如果不执行,那么事件还会一级一级的往下走,直到被拦截或者到最底层然后执行onTouchEvent,这就是事件分发

但是子view会有所谓的“尚方宝剑”,我们知道事件冲突会有内部拦截和外部拦截,那么内部是如何拦截的呢?

如下图所示,在viewgroup里面的dispatchTouchEvent方法里面,有这样一段代码,那么他的作用是什么呢?

通过上面的学习,我们知道事件是一层一层往下传递的,那么父view很可能会将事件进行拦截,这样来说对子view是不公平的。因此子view可以通过内部拦截,请求父view不要拦截事件,告诉父view这个事件是我的,那么这个标志位就是下图代码disallowIntercept变量。

                    图5

 

 

3、View和ViewGroup的分发流程

事件分发简易流程

首先判断是否有子view拦截,也就是上面所说的尚方宝剑,如果子view不需要,则判断自身是否需要拦截。

                    图6

 

事件分发进阶流程

                    图7

 

4、解决滑动冲突

                        图8

图8是整个手指在屏幕滑动的时候所触发的各个函数以及流程。我们直到,嵌套滑动是包含两个角色的,一个是父view,一个子view,那么父view是需要实现NestedScrollingParent,子view是需要实现NestedScrollingChild

这也是为什么我们后面的代码用到的是NestedScrollView,而不是ScrollView。

图示我们把view当成界面,NestedScrollingChild当做recyclerView,NestedScrollingParent当做是NestedScrollView,这样方便理解一点,因为淘宝首页二级联动就是这样嵌套的,一下也以这个为思路。

当点击view之后,recyclerView执行4、5、6步,找到自己的父view——NestedScrollView,然后滑动的时候执行7、8步,获取到父view是否需要滑动,如果需要滑动则只滑动父view就可以了。

但是在第8步的时候,父view会直接把事件传递给他自己的父view,也就是事件会传递到NestedScrollView的父亲。因为NestedScrollView实现了NestedScrollingParent接口,同时也实现了NestedScrollingChild接口

所以他会跟recyclerView一样,把事件传递给他的父view,但是他的父view实际上是一个linearLayout了,这不是我们需要的,因此我们需要重写一个NestedScrollView,重写他的onNestedPreScroll方法。

Fling即为惯性滑动,通过速度算出距离。

完。

posted @ 2020-12-19 17:08  金大人的梦  阅读(586)  评论(0编辑  收藏  举报