Vertical ViewPager and Android Pie Inconsistent Behavior with Swipe Gesture

前端 未结 3 1921
清歌不尽
清歌不尽 2020-12-28 09:25

My problem is closely related to two other questions that haven\'t been answered yet.

ViewPager not responding to touch in layout area created dynamically in Fragmen

3条回答
  •  不思量自难忘°
    2020-12-28 09:58

    After spending hell amount of time on SO, trying many GitHub libraries and waiting for someone to respond on the bounty, then I came up with below solutions and hope that it helps whoever needs it.

    At first, this question got my attention and I think most of the answers over there are helpful, hence I upvoted them. The main answer which helped me are link-1 and link-2.

    Even though I have to make a few minor changes to ignore horizontal swipe fling events.

    Please do try this code and provide your feedback for any further improvements, thanks in advance. Happy Coding :)

    import android.content.Context;
    import android.support.v4.view.MotionEventCompat;
    import android.support.v4.view.ViewPager;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    
    public class VerticalViewPager extends ViewPager {
        float x = 0;
        float mStartDragX = 0;
        private static final float SWIPE_X_MIN_THRESHOLD = 50; // Decide this magical nuber as per your requirement
    
        public VerticalViewPager(Context context) {
            super(context);
            init();
        }
    
        public VerticalViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            // The majority of the magic happens here
            setPageTransformer(true, new VerticalPageTransformer());
            // The easiest way to get rid of the overscroll drawing that happens on the left and right
            setOverScrollMode(OVER_SCROLL_NEVER);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (getAdapter() != null) {
                if (getCurrentItem() >= 0 || getCurrentItem() < getAdapter().getCount()) {
                    swapXY(event);
                    final int action = event.getAction();
                    switch (action & MotionEventCompat.ACTION_MASK) {
                        case MotionEvent.ACTION_MOVE:
                            break;
                        case MotionEvent.ACTION_UP:
                            mStartDragX = event.getX();
                            if (x < mStartDragX
                                    && (mStartDragX - x > SWIPE_X_MIN_THRESHOLD)
                                    && getCurrentItem() > 0) {
                                Log.i("VerticalViewPager", "down " + x + " : " + mStartDragX + " : " + (mStartDragX - x));
                                setCurrentItem(getCurrentItem() - 1, true);
                                return true;
                            } else if (x > mStartDragX
                                    && (x - mStartDragX > SWIPE_X_MIN_THRESHOLD)
                                    && getCurrentItem() < getAdapter().getCount() - 1) {
                                Log.i("VerticalViewPager", "up " + x + " : " + mStartDragX + " : " + (x - mStartDragX));
                                mStartDragX = 0;
                                setCurrentItem(getCurrentItem() + 1, true);
                                return true;
                            }
                            break;
                    }
                } else {
                    mStartDragX = 0;
                }
                swapXY(event);
                return super.onTouchEvent(swapXY(event));
            }
            return false;
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
            boolean intercepted = super.onInterceptTouchEvent(swapXY(event));
            switch (event.getAction() & MotionEventCompat.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    x = event.getX();
                    break;
            }
            swapXY(event); // return touch coordinates to original reference frame for any child views
            return intercepted;
        }
    
        /**
         * Swaps the X and Y coordinates of your touch event.
         */
        private MotionEvent swapXY(MotionEvent ev) {
            float width = getWidth();
            float height = getHeight();
    
            float newX = (ev.getY() / height) * width;
            float newY = (ev.getX() / width) * height;
    
            ev.setLocation(newX, newY);
    
            return ev;
        }
    
        private class VerticalPageTransformer implements PageTransformer {
            @Override
            public void transformPage(View view, float position) {
    
                if (position < -1) { // [-Infinity,-1)
                    // This page is way off-screen to the left.
                    view.setAlpha(0);
    
                } else if (position <= 1) { // [-1,1]
                    view.setAlpha(1);
    
                    // Counteract the default slide transition
                    view.setTranslationX(view.getWidth() * -position);
    
                    //set Y position to swipe in from top
                    float yPosition = position * view.getHeight();
                    view.setTranslationY(yPosition);
    
                } else { // (1,+Infinity]
                    // This page is way off-screen to the right.
                    view.setAlpha(0);
                }
            }
        }
    }
    

提交回复
热议问题