2020-01-16:为什么ViewPager嵌套ViewPager,内部的ViewPager滚动没有被拦截?
MoJieBlog opened this issue · comments
MoJieBlog commented
hfr92 commented
xuensheng commented
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//省略若干代码
// Nothing more to do here if we have decided whether or not we
// are dragging.
//1、move再次进来时mIsUnableToDrag为true
if (action != MotionEvent.ACTION_DOWN) {
if (mIsBeingDragged) {
if (DEBUG) Log.v(TAG, "Intercept returning true!");
return true;
}
//2、由于mIsUnableToDrag为true所以不拦截,move事件正常传递给子ViewPager
if (mIsUnableToDrag) {
if (DEBUG) Log.v(TAG, "Intercept returning false!");
return false;
}
}
switch (action) {
case MotionEvent.ACTION_MOVE: {
//省略若干代码,关键点在于canScroll方法,此处会寻找可滑动的子View
if (dx != 0 && !isGutterDrag(mLastMotionX, dx)
&& canScroll(this, false, (int) dx, (int) x, (int) y)) {
// Nested view has scrollable area under this point. Let it be handled there.
mLastMotionX = x;
mLastMotionY = y;
mIsUnableToDrag = true;//第一次move事件进来时,设置此值为true,下一次move事件进来时,onInterceptTouchEvent直接返回false,看上面1和2
return false;
}
//省略若干代码
break;
}
//省略若干代码
}
//省略若干代码
return mIsBeingDragged;
}
//此方法递归寻找可滑动的子View,找到后返回true
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ViewGroup) {
final ViewGroup group = (ViewGroup) v;
final int scrollX = v.getScrollX();
final int scrollY = v.getScrollY();
final int count = group.getChildCount();
// Count backwards - let topmost views consume scroll distance first.
for (int i = count - 1; i >= 0; i--) {
// TODO: Add versioned support here for transformed views.
// This will not work for transformed views in Honeycomb+
final View child = group.getChildAt(i);
if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight()
&& y + scrollY >= child.getTop() && y + scrollY < child.getBottom()
&& canScroll(child, true, dx, x + scrollX - child.getLeft(),
y + scrollY - child.getTop())) {
//当child为ViewPager时,返回true
return true;
}
}
}
return checkV && v.canScrollHorizontally(-dx);
}
答案:ViewPager重写了onInterceptTouchEvent方法,同时在move事件里边递归寻找可滑动的子View(ViewPager),,当它找到可滑动的子View(ViewPager)时,onInterceptTouchEvent返回false,也就是不拦截事件,所以子ViewPager可以滑动
senlinxuefeng commented