子View重写dispatchTouchEvent方法
var mLastX = 0f
var mLastY = 0f
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
val x = ev.x
var y = ev.y
when(ev?.action){
MotionEvent.ACTION_DOWN->{
parent.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_MOVE->{
var deltaX = x - mLastX
var deltaY = y - mLastY
if(满足父布局滑动条件){
parent.requestDisallowInterceptTouchEvent(false)
}
}
}
mLastX = x
mLastY = y
var result = super.dispatchTouchEvent(ev)
Log.e("gacmy","View1 dispatchTouchEvent:${result}")
return result
}
父布局重写onInterceptTouchEvent方法,处理ACTION_DOWN返回false 其他情况都返回true
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
var intercpted = MotionEvent.ACTION_DOWN != ev?.action
Log.e("gacmy","ViewGroup2 onInterceptTouchEvent:${intercpted}")
return intercpted
}
分析ViewGroup dispatchTouchEvent代码
//这个条件满足需要发生ACTION_DOWN事件,
//或者mFirstTouchTarget != null
//只要父布局事件成功派发,子View dispatchTouchEvent返回true,则mFirstTouchTarget != null 成立
//后续ACTION_MOVE 也会满足这个if条件
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
//子布局ACTION_DOWN事件设置了这个标志位,
//再后续ACTION_MOVE 事件中只有子布局里的滑动事件没有满足父布局的滑动条件,则disallowIntercept 永远等于true
//下面的intercepted = false
//父布局就不会拦截子布局的事件
//如果子布局滑动事件满足父布局的滑动条件,此时,disallowIntercept= false
//一定会调用父布局onInterceptTouchEvent方法,这个时候,不是ACTION_DOWN 肯定返回true,父布局就会拦截子布局的事件,后续事件不会再传入子布局。
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
intercepted = true;
}