Search code examples
androidkotlinandroid-viewpager2

How to disable swiping in specific direction in ViewPager2


I want to disable right to left swipe in ViewPager2. I basically have a viewpager2 element with 2 pages in my navigation drawer. I want my second page to show up only when I click some element in my first page (right to left swipe from the first page should not open the second page), while when I'm in the second page, the viewpager2 swipe (left to right swipe) should swipe as it should do in viewpager.

I've tried extending the ViewPager2 class and override the touch events, but unfortunately it ViewPager2 is a final class, so I cannot extend it.

Secondly, I tried to use setUserInputEnabled method to false, but this disabled all swipes altogether (I just want to disable right to left swipe). If I could find some listener which checks for the current page before swiping and disable swipe otherwise, it would probably work.

     implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha05'

Code for setting up of ViewPager2

      ViewPager2 pager = view.findViewById(R.id.pager);
      ArrayList<Fragment> abc = new ArrayList<>();
      abc.add(first);
      abc.add(second);
      navigationDrawerPager.setAdapter(new DrawerPagerAdapter(
                this, drawerFragmentList));
      pager.setAdapter(new FragmentStateAdapter(this), abc);

Solution

  • I found a listener which can listen when the user tries to swipe, it'll then check the current page, if it's the first page, disable the user input else enable it as it was by default.

    Here's the code snippet for that

    In Java:

    pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageScrollStateChanged(int state) {
            super.onPageScrollStateChanged(state);
    
            if (state == SCROLL_STATE_DRAGGING && pager.getCurrentItem() == 0) {
                pager.setUserInputEnabled(false);
            } else {
                pager.setUserInputEnabled(true);
            }
        }
    });
    

    In Kotlin:

    viewPager.registerOnPageChangeCallback(object : OnPageChangeCallback() {
        override fun onPageScrollStateChanged(state: Int) {
            super.onPageScrollStateChanged(state)
    
            viewPager.isUserInputEnabled = !(state == SCROLL_STATE_DRAGGING && viewPager.currentItem == 0)
        }
    })
    

    Since my scenario was of 2 pages only, checking the page number would be good for me, but in case we have more than 2 pages and we need to disable the swipe in one particular direction, we may use onPageScrolled(int position, float positionOffset, int positionOffsetPixels) listener of viewpager2 and handle the desired scenario according to the positive or negative values of position and positionOffset.