ViewPager disable swiping to a certain direction
Asked Answered
B

7

24

I want to disable the swiping, but only to the right side. I found a working solution in this answer. Unfortunately, this copies the whole ViewPager source to achieve the goal. Is there any methods just inheriting the existing class and not duplicating?

Bisson answered 6/9, 2013 at 14:19 Comment(6)
Are you bound to use vanilla ViewPager?Jolley
If there is a lib which contains a ViewPager with this behavior, i can use it BTW. Note that i want to dynamically enable and disable right swiping, not just disable it statically.Bisson
I suppose you could try overriding onTouchEvent or onInterceptTouchEvent and try to filter out the touch events you don't want it to respond to (and call super for the rest).Ladner
Actually i have to copy everything because i want to modify a private method. :(Bisson
Preventing swipes is really easy, a single method call. Preventing them only to one side could prove a bit more difficult...Jolley
Create an object that extend ViewPager and do the custom work ;)Fimble
U
25

I'm not sure this is exactly what you need: I needed a viewpager for a wizard with a max page that the user can't pass it.

At the end the solution was in the adapter. I changed the count of the PagerAdapter and this way blocks the user from passing the max page:

@Override
public int getCount() {
    return mProgress; //max page + 1
}

When the user progresses to the next page:

private void setWizardProgress(int progress) {
    if(progress > mProgress) {
        mProgress = progress;
        mWizardPagerAdapter.notifyDataSetChanged();
    }
}

This way when the user is at max page he can't scroll to the right.

Unreflecting answered 6/2, 2014 at 12:46 Comment(2)
Thanks! This is an old question, i already resolved this (via dropping ViewPager and using Fragment animations so i can completely control the flow). I think yours is a good solution, so i am accepting it. :)Bisson
how did you do this can you share a snippet? how did you disable the swap on right side with this example.Bootstrap
I
23

Here is working ViewPager class with possibility to disable any direction paging. Check out all the answer here .

public class CustomViewPager extends ViewPager {
    private float initialXValue;
    private SwipeDirection direction;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.direction = SwipeDirection.all;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (this.IsSwipeAllowed(event)) {
            return super.onTouchEvent(event);
        }

        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (this.IsSwipeAllowed(event)) {
            return super.onInterceptTouchEvent(event);
        }

        return false;
    }

    private boolean IsSwipeAllowed(MotionEvent event) {
        if(this.direction == SwipeDirection.all) return true;

        if(direction == SwipeDirection.none )//disable any swipe
            return false;

        if(event.getAction()==MotionEvent.ACTION_DOWN) {
            initialXValue = event.getX();
            return true;
        }

        if(event.getAction()==MotionEvent.ACTION_MOVE) {
            try {
                float diffX = event.getX() - initialXValue;
                if (diffX > 0 && direction == SwipeDirection.right ) {
                    // swipe from left to right detected
                    return false;
                }else if (diffX < 0 && direction == SwipeDirection.left ) {
                    // swipe from right to left detected
                    return false;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }

        return true;
    }

    public void setAllowedSwipeDirection(SwipeDirection direction) {
        this.direction = direction;
    }
Infect answered 3/12, 2015 at 21:43 Comment(7)
This thing actually works. (Though the syntax styling is very bad)Parlour
@vedant1811 what's so bad about i?Argo
@Argo probably means the lack of autoformat, IsSwipeAllowed with a big first letter, the try-catch where no exception is thrown and also the printStackTrace there, and "this" at unnecessary places (and the overriden methods could actually be inlined). But the answer is helpful anyway.Authorship
Hi, @Infect This works fine with normal pages. But if pages contains EditText the touch is disabled so... This solution not work in that case.Semitics
Have you tried this solution with multitouch swipe?Leftist
@Viacheslav, didn`t try it yetInfect
The try-catch block is unnecessary. Nothing inside it will throw an exception.Adherent
S
10

Another simple way is to use setCurrentItem() to scroll back to the desired slide if you hit a certain position. For instance, this will only allow forward swiping:

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

    @Override
    public void onPageSelected(int position) {
        if(position < mProgress) {
            mViewPager.setCurrentItem(mProgress, true);
        } else {
            mProgress = position;
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {}
});

Or if you want to have a max slide:

if(position > 4) {
    mViewPager.setCurrentItem(4, true);
}

This solution will technically not completely disable the swipe, as you'll still see a small portion of the disallowed slide when you make your swipe movement. But for some applications this may be preferred.

Spelunker answered 18/8, 2016 at 13:27 Comment(0)
O
5

You can try following:

Step 1: Create a new custom class say "CustomViewPager". The class inherits from "ViewPager" and includes a new customised method called "setPagingEnabled" with a purpose to enable / disable the swiping, depending on the requirement.

Step2 : Override two methods: "onTouchEvent" and "onInterceptTouchEvent". Both will return "false" if the paging is to be disabled completely.

Step 3: Substitute the "ViewPager" tag on the layout file with customized class:

    <package_name.customviewpager 
     android:id="@+id/customViewPager" 
     android:layout_height="match_parent" 
     android:layout_width="match_parent" />

Step 4: CustomViewPager.java

    public class CustomViewPager extends ViewPager {

private boolean enabled;

public CustomViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.enabled = true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (this.enabled && detectSwipeToRight(event)) {
        return super.onTouchEvent(event);
    }

    return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (this.enabled && detectSwipeToRight(event)) {
        return super.onInterceptTouchEvent(event);
    }

    return false;
}

// To enable/disable swipe 
public void setPagingEnabled(boolean enabled) {
    this.enabled = enabled;
}

// Detects the direction of swipe. Right or left. 
// Returns true if swipe is in right direction
public boolean detectSwipeToRight(MotionEvent event){

 int initialXValue = 0; // as we have to detect swipe to right
 final int SWIPE_THRESHOLD = 100; // detect swipe
 boolean result = false;

        try {                
            float diffX = event.getX() - initialXValue;

                if (Math.abs(diffX) > SWIPE_THRESHOLD ) {
                    if (diffX > 0) {
                        // swipe from left to right detected ie.SwipeRight
                        result = false;
                    } else {
                        // swipe from right to left detected ie.SwipeLeft
                        result = true;
                    }
                }
            } 
         catch (Exception exception) {
            exception.printStackTrace();
        }
        return result;
    }
}
Onstad answered 6/9, 2013 at 15:14 Comment(4)
I tried the updated answer. diffX is always positive, so the method never returns true.Bisson
Hi wonderCsabo : did you get any soluton for the same ? i also tried lots of but still this type issue facing. Waiting for your replay. Thanks in advance.Osmometer
This doesn't detect a swipe, it just detects if the first (and every subsequent) motion event X coordinate is greater than 0. This should always return false because X will always be positive.Intelligibility
yes Hamid ,due to to this it disables swipe in both directions.Arsonist
A
3

You can use the methods beginFakeDrag() and endFakeDrag().

beginFakeDrag() when you want disable the swipe and endFakeDrag() if you want enable again.

Like this: viewPager.beginFakeDrag();

Allium answered 21/8, 2014 at 9:23 Comment(0)
D
1
private float initialXValue;
@Override
public boolean onTouchEvent(MotionEvent event) {
    if (this.mEnabled) {
        return super.onTouchEvent(event);
    }
    if(event.getAction()==MotionEvent.ACTION_DOWN){
        initialXValue = event.getX();
    }else if(event.getAction()==MotionEvent.ACTION_MOVE){
        if(detectSwipeToRight(event)){
            System.out.println("right swipe detected");
        }
    }
    return true;
}

private boolean detectSwipeToRight(MotionEvent event) {
    final int SWIPE_THRESHOLD = 100; // detect swipe
    boolean result = false;

    try {
        float diffX = event.getX() - initialXValue;
        if (Math.abs(diffX) > SWIPE_THRESHOLD) {
            if (diffX < 0) {
                // swipe from right to left detected ie.SwipeLeft
                result = true;
            }
        }
    } catch (Exception exception) {
        exception.printStackTrace();
    }
    return result;
}
Drumfish answered 21/6, 2014 at 10:48 Comment(1)
This would be a much better answer if you explained the code a bit more.Kawai
B
-3

You have to create your own ViewPager subclass and override the canScrollHorizontally function

http://developer.android.com/reference/android/support/v4/view/ViewPager.html#canScrollHorizontally(int)

Bombe answered 6/9, 2013 at 14:31 Comment(2)
Then try the canScroll method, I used it and it is calledBombe
never gets called eitherDiscovert

© 2022 - 2024 — McMap. All rights reserved.