分发 dispatchTouchEvent 触碰屏幕时会触发的view方法,原理需要看更深层次的源码,这里可以理解为入口
拦截 onInterceptTouchEvent
消费 onTouchEvent
总结
View中有 dispatchTouchEvent分发 onTouchEvent消费
ViewGroup是由多个View组成。继承View 有onInterceptTouchEvent拦截 和 重写了dispatchTouchEvent分发
ConstraintLayout、ViewPager、LinearLayout、RelativeLayout、FrameLayout等又是继承ViewGroup
我们在这些布局中重写的onTouchEvent都是重写的View中的onTouchEvent
事件是往下传递的
事件处理了又是往上汇报的
一、Activity开始
设置点击事件都是基于view 而Activity的view又是来源于我们设置的setContentView
再看getWindow() 发现是个DecorView,而DecorView 继承 FrameLayout。FrameLayout又是继承ViewGroup
Activity -> Window -> DecorView -> FrameLayout -> ViewGroup
二、ViewGroup dispatchTouchEvent方法
ViewGroup是继承View 重写了dispatchTouchEvent方法
代码很多,逻辑很多,看的很懵逼。但是只找关键代码,往下看
首先是检查拦截
记住intercepted是拦截变量。
再往下看
这个 if 里面的代码比较多,也挑重点看看
添加触碰目标。进入这个方法看看
主要功能是根据二进制的指针ID从子View中获取触碰目标
mFirstTouchTarget 的描述是 First touch target in the linked list of touch targets.大概的意思是 触摸目标链表中的第一个触摸目标。
next顾名思义就是下一个的意思
刚开始mFirstTouchTarget为null的话,next就是null,mFirstTouchTarget再重新赋值
触碰目标
回到dispatchTouchEvent方法中
如果上面的if语句中 取消或者拦截 一方为true,则不会进入addTouchTarget 方法,mFirstTouchTarget肯定也是为null的
再往下看
不论mFirstTouchTarget是否为空
,都会执行dispatchTransformedTouchEvent这个方法。
区别只是child view是否为空
看下dispatchTransformedTouchEvent这个方法,返回值是boolean类型
OK,都是调用View的dispatchTouchEvent方法,不管是ViewGroup本身的,还是子View
得出结论如果ViewGroup的onInterceptTouchEvent拦截方法返回为true,则触碰事件在ViewGroup这层就被消费,无法往ViewGroup中的子View走下去
三、View dispatchTouchEvent方法
这个方法的返回值,可以查看上面流程。最终回到的还是View dispatchTouchEvent或者ViewGroup dispatchTouchEvent
从返回值来看,只有2种情况,没有焦点直接返回false 另外个就是result了
1、如果你设置了view的OnTouchListener 并且在onTouch方法中返回true 也不会往下走了
2、如果重写onTouchEvent,返回值为true,result则为true,代表已经处理
四、View onTouchEvent方法
手势有几个属性,先从按下开始吧
MotionEvent.ACTION_DOWN中
1方法里面 也是调用了2方法
checkForLongClick方法----》CheckForLongPress方法
performLongClick方法----》performLongClickInternal方法
扯得有点远,拉回
MotionEvent.ACTION_UP
如果长按监听返回的是false,才会往下执行点击
追着performClick下去 会发现有个li.mOnClickListener.onClick(this); 执行点击事件
14年的时候看过的东西,只是源码也改动很大。最近整理点东西,给自己留个备份