VerticalPager中的NestedScrollView无法正常工作

时间:2018-11-25 16:29:58

标签: android android-viewpager android-nestedscrollview

我从NestedScrollView创建了这个扩展类,以便当用户从scoll视图着陆时将事件调度到父级(我的ViewPager)。这种行为效果很好。

滚动视图用红色矩形表示:

enter image description here

:如果滚动视图位于底部,并且我想从滚动视图(滚动!)滑至下一个屏幕(下方),则viewpager不会什么都不要做。我该怎么办?

非常感谢!

public class VerticalNestedScrollview extends NestedScrollView {

    public class VerticalPagerTouchDownEvent extends BaseEvent {
    }

    private long mDownTime;
    private final long mAreaThreshold = 60; // In pixels
    private boolean mCatchMoveTouchEvent = true;
    private int mDownX, mDownY, mPagesCount = 0;
    private ViewPager mParentViewPager;
    private boolean mIsBottomReached = false, mIsTopReached = true;

    public VerticalNestedScrollview(Context context) {
        super(context);
        init();
    }

    public VerticalNestedScrollview(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public VerticalNestedScrollview(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        ViewTreeObserver observer = getViewTreeObserver();
        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mParentViewPager = getViewPagerParent();
                if (mParentViewPager != null) {
                    PagerAdapter pagerAdapter = mParentViewPager.getAdapter();
                    mPagesCount = pagerAdapter.getCount();
                }
                int contentHeight = getChildAt(0).getHeight();
                mCatchMoveTouchEvent = getHeight() < contentHeight + getPaddingTop() + getPaddingBottom();
            }
        });
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);

        refreshTopBottomReachedInfos();

        super.onScrollChanged(l, t, oldl, oldt);
    }

    private void refreshTopBottomReachedInfos() {
        mIsTopReached = getScrollY() == 0;

        // Grab the last child placed in the ScrollView, we need it to determinate the bottom position.
        View view = getChildAt(getChildCount() - 1);

        // Calculate the scroll diff
        int diff = (view.getBottom() - (getHeight() + getScrollY())) + getPaddingBottom();

        // if diff is zero, then the bottom has been reached
        mIsBottomReached = diff <= 0;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mCatchMoveTouchEvent) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                mDownTime = SystemClock.uptimeMillis();
                mDownX = (int) ev.getRawX();
                mDownY = (int) ev.getRawY();

                refreshTopBottomReachedInfos();

            } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
                Rect rect = new Rect();
                getHitRect(rect);
                rect.bottom += mAreaThreshold;
                rect.top -= mAreaThreshold;
                boolean isDownSwipe = mDownY > (int) ev.getRawY();  

                // The move action is outside this scrollview
                if (!rect.contains((int) ev.getX(), (int) ev.getY())) {
                    dispatchTouchDownToViewPager(ev, isDownSwipe, 0);
                    return true;
                }                        

            } else {
                mIsBottomReached = false;
                mIsTopReached = false;
            }

            return super.dispatchTouchEvent(ev);

        } else {
            return true;
        }
    }

    private boolean checkDispatchValidity(boolean isDownSwipe) {
        if (isDownSwipe && mParentViewPager != null &&
                mParentViewPager.getCurrentItem() == mPagesCount - 1)
            return false;

        if (!isDownSwipe && mParentViewPager != null &&
                mParentViewPager.getCurrentItem() == 0)
            return false;

        return true;
    }

    private void dispatchTouchDownToViewPager(MotionEvent ev, boolean isDownSwipe, long deltaY) {
        if (checkDispatchValidity(isDownSwipe)) {
            MotionEvent motionEvent = MotionEvent.obtain(
                    mDownTime,
                    SystemClock.uptimeMillis() + 1000,
                    MotionEvent.ACTION_DOWN, (int) ev.getRawX(),
                    (int) ev.getRawY() - deltaY, 0
            );

            if (mParentViewPager != null) {
                mParentViewPager.dispatchTouchEvent(motionEvent);
                EventBus.getDefault().post(new VerticalPagerTouchDownEvent());
            }
        }
    }

    private ViewPager getViewPagerParent() {
        ViewParent parent = getParent();
        do {
            if (parent instanceof ViewPager) {
                return ((ViewPager) parent);
            }
            parent = parent.getParent();
        } while (parent != null);
        return null;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        super.onTouchEvent(ev);
        return true;
    }
}

0 个答案:

没有答案