BioeJD
BioeJD

Reputation: 243

Temporarily/Dynamically disable single page in Viewpager

I have an extended FragmentPagerAdapter that provides 3 fragments to a ViewPager, giving me 3 pages that I can either swipe between or use the tabs I've added to the actionbar to manually choose a page.

I'd like to temporarily disable the user from accessing the final page (a more generalized solution to disable any specific page would also be interesting, but not necessary) with either navigation type. I will then re-enable their access with a callback from one of the fragments.

I've read through answers to some similar questions about not allowing swiping by overriding onTouchEvent and onInterceptTouchEvent, and then using some custom gesture detection within those, or even a half solution using beginFakeDrag().

My current solution simply sets a smaller item count in the adapter, making sure to use notifyDataSetChanged(), and changes it back when necessary. Are there any elegant alternatives to these approaches, maybe one that doesn't require changing the dataset?

I also see that ActionBar.Tab doesn't have a setEnable() method, and most suggest to just remove the tab. Is there a way I can have a tab remain visible but not selectable? My approach has been to define which tab is disabled and reselect the previously selected tab if the user selects the disabled one.

Edit: I aim to disable both tabbing and swiping to the last page.

Upvotes: 5

Views: 3497

Answers (1)

Andrea Thacker
Andrea Thacker

Reputation: 3470

You're definitely going to want to create your own custom ViewPager subclass. I created a simple custom ViewPager called CustomSwipePager that will handle blocking user interaction when needed.

public class CustomSwipeViewPager extends ViewPager {

    private boolean mLastPageEnabled = false;
    private int mLastPageIndex = 0;

    public NoSwipeViewPager(Context context) {
        super(context);
    }

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

    public void setLastPageEnabled(boolean enabled) {
        mLastPageEnabled = enabled;
    }

    public void setLastPageIndex(int index) {
        mLastPageIndex = index;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event){

        if(!mLastPageEnabled && getCurrentItem() >= (mLastPageIndex - 1)) {
            // Always return false to disable user swipes
            return false;
        }

        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (!mLastPageEnabled && getCurrentItem() >= (mLastPageIndex - 1)) {
            // Always return false to disable user swipes
            return false;
        }

        return true;
    }
}

There are two key methods you will want to take advantage of in the class setLastPageEnabled() and setLastPageIndex(). You can set the last page index to whatever you need, in your case if you have three items you would set it to 2. Then also use setLastPageEnabled(false) to disable swiping or to re-enabled use setLastPageEnabled(true).

You can include this custom view into your layout like this:

<com.mypackage.CustomSwipeViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_swipe_view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

And finally reference it in your Fragment or Activity in the appropriate place:

private CustomSwipeViewPager mPager;

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);

    mPager = (CustomSwipeViewPager) findViewById(R.id.custom_swipe_view_pager);
    mPager.setLastPageEnabled(false);
    mPager.setLastPageIndex(2);
}

Upvotes: 6

Related Questions