Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2020-01-16:为什么ViewPager嵌套ViewPager,内部的ViewPager滚动没有被拦截? #235

Open
MoJieBlog opened this issue Jan 16, 2020 · 3 comments

Comments

@MoJieBlog
Copy link
Collaborator

No description provided.

@hfr92
Copy link

hfr92 commented Oct 21, 2020

被外部的ViewPager拦截了,需要做滑动冲突处理。重写子View的 dispatchTouchEvent方法,在子View需要拦截的时候进行拦截,否则交给父View处理。
image

@aositeluoke
Copy link

aositeluoke commented Dec 3, 2020

@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
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants