内部拦截法:
在布局中使用 com.xxx.xxx.view.ScrollLinearLayout (相当于线性布局LinearLayout)来嵌套冲突的控件,例如ViewPager 等等。内部拦截法是指父容器不拦截任何触摸事件,所有的触摸事件都传递给子元素,如果子元素需要此触摸事件就直接消耗掉,否则就交由父容器进行处理,这种方法和Android中的事件传递、处理机制不一致,需要配合requestDisallowInterceptTouchEvent方法才能正常工作,使用起来比外部拦截法稍显复杂。这种方法需要重写子元素的dispatchTouchEvent方法和父容器的onInterceptTouchEvent方法。
内部拦截主要依赖于requestDisallowInterceptTouchEvent方法,它用于设置父控件的FLAG_DISALLOW_INTERCEPT标志,这个标志可以决定父控件是否拦截事件,如果设置了这个标志则不拦截;如果没设这个标志,就会调用父控件的onInterceptTouchEvent来询问父控件是否拦截。但这个标志对Down事件无效。
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class ScrollLinearLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0) :
LinearLayout(context, attrs, defStyleAttr, defStyleRes){
private var mLastX = 0.0f
private var mLastY = 0.0f
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
val x = ev.x
val y = ev.y
when(ev.action){
MotionEvent.ACTION_DOWN->{
parent.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_MOVE->{
val deltaX = x - mLastX
val deltaY = y -mLastY
if (Math.abs(deltaX)>Math.abs(deltaY)){
//
parent.requestDisallowInterceptTouchEvent(false)
}
}
}
mLastX = x
mLastY = y
return super.dispatchTouchEvent(ev)
}
}



