613

I have ViewPager and below it I have 10 buttons. By clicking on button, for example #4, the pager goes immediately to page #4 by mPager.setCurrentItem(3);. But, I want to disable the paging by swiping with finger horizontally. Thus, the paging is done ONLY by clicking on the buttons. So, how I can disable the swiping with finger?

theateist
  • 13,879
  • 17
  • 69
  • 109
  • How about using [ViewFlipper](https://developer.android.com/reference/android/widget/ViewFlipper) in the first place? It will save you a great deal of a headache. – Alex Semeniuk Jul 17 '19 at 11:49
  • 2
    With ViewPager2, disabling the swipe takes just one line of code: https://stackoverflow.com/questions/54978846/how-to-disable-swiping-in-viewpager2 – Kraigolas Oct 21 '20 at 19:46

27 Answers27

922

You need to subclass ViewPager. onTouchEvent has a lot of good things in it that you don't want to change like allowing child views to get touches. onInterceptTouchEvent is what you want to change. If you look at the code for ViewPager, you'll see the comment:

    /*
     * This method JUST determines whether we want to intercept the motion.
     * If we return true, onMotionEvent will be called and we do the actual
     * scrolling there.
     */

Here's a complete solution:

First, add this class to your src folder:

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
import java.lang.reflect.Field;

public class NonSwipeableViewPager extends ViewPager {

    public NonSwipeableViewPager(Context context) {
        super(context);
        setMyScroller();
    }

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    //down one is added for smooth scrolling

    private void setMyScroller() {
        try {
            Class<?> viewpager = ViewPager.class;
            Field scroller = viewpager.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            scroller.set(this, new MyScroller(getContext()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class MyScroller extends Scroller {
        public MyScroller(Context context) {
            super(context, new DecelerateInterpolator());
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
        }
    }
}

Next, make sure to use this class instead of the regular ViewPager, which you probably specified as android.support.v4.view.ViewPager. In your layout file, you'll want to specify it with something like:

<com.yourcompany.NonSwipeableViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

This particular example is in a LinearLayout and is meant to take up the entire screen, which is why layout_weight is 1 and layout_height is 0dp.

And setMyScroller(); method is for smooth transition

jungledev
  • 4,195
  • 1
  • 37
  • 52
louielouie
  • 14,881
  • 3
  • 26
  • 31
  • 3
    @louielouie On a side-note: is there any particular reason, why you chose the `0dp` height/`1` weight solution over `match_parent` height to achieve the full-screen effect? Do you gain performance improvements by doing so? – ubuntudroid Aug 21 '13 at 07:28
  • @ubuntudroid For the answer to the 0dp height/1 weight, please read this Q&A: http://stackoverflow.com/questions/12016781/why-is-0dp-considered-a-performance-enhancement – louielouie Aug 21 '13 at 15:22
  • Something I missed or someone else would miss: Don't forget to change all ViewPager classes in your Java file to NonSwipeableViewPager. Don't miss any. Great answer! – RicNjesh Apr 24 '14 at 10:05
  • 31
    This answer does not prevent page swiping when using the keyboard left/right keys (try it in the emulator). May not be a problem for touch devices but with TV and laptops it may be one. – Vincent Mimoun-Prat Aug 03 '14 at 13:50
  • 1
    It worked for me, but I'm including this "static" ViewPager inside another ViewPager and at this page I can't swipe parent ViewPager. How can I get this to work? – edrian Aug 29 '14 at 15:32
  • @MarvinLabs In order to prevent paging through keyboard (dpad) you can override `arrowScroll()` in the same way the other methods are overridden (or even the same way as the one suggested in the answer by @Rajul ). – Thorbear Jan 19 '15 at 15:34
  • 8
    @MarvinLabs @Thorbear The correct way to disable the page scroll by keyboard is to override the `executeKeyEvent()`. This is the method that then call `allowScroll()`. `// Never allow swiping by keyboard LEFT, RIGHT, TAB and SHIFT+TAB keys` `@Override public boolean executeKeyEvent(KeyEvent event) { return false; }` – araks Mar 09 '15 at 17:14
  • 7
    well, this disables also the vertical scrolling... this is bad, if you're using listviews. – maysi Sep 20 '15 at 13:09
  • 2
    Still scroll page little bit. but if you keep swipe it it will eventually scrolling the page. – Akirayjin Sep 21 '15 at 05:49
  • 5
    I hope google could have just provided a method to which we supply our interface method on how to handle touches/swiping because I believe it wouldn't hurt? – Neon Warge Nov 14 '15 at 13:58
  • @louielouie in your answer you mentioned that you can use onTouchEvent to allow child views to receive touches.Can you make items inside a recyclerview which is the child of a ViewPager swipeable with this method? – Jamie-505 Jun 26 '16 at 22:03
  • working fine for me. I was having a problem previously that i disable swiping between pager but the editext able to swipe the pager. – mmw5610 Dec 18 '16 at 17:49
  • @louielouie how can i use that programical ? – tux-world Jun 24 '17 at 07:11
  • 2
    relying on variable name "mScroller" which can be changed in future is not a good solution. – matoni Jul 08 '17 at 09:14
  • Remember use – Andy Sander Dec 06 '17 at 01:12
  • 2
    First, don't override `onInterceptTouchEvent()` - it will prevent child views to receive input. Second, don't use reflection to get access to private fields (especially in production systems) - you might get problems in the future. Third, read documentation on what result `onTouchEvent()` should return. Forth, to disable 'swipes by little bit' you can try overriding the following method: `protected void onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) { scrollTo(0, 0); }`. – Alex Semeniuk Jul 16 '19 at 14:52
488

The more general extension of ViewPager would be to create a SetPagingEnabled method so that we can enable and disable paging on the fly. To enable / disable the swiping, just overide two methods: onTouchEvent and onInterceptTouchEvent. Both will return "false" if the paging was disabled.

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) {
            return super.onTouchEvent(event);
        }

        return false;
    }

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

        return false;
    }

    public void setPagingEnabled(boolean enabled) {
        this.enabled = enabled;
    } 
}

Then select this instead of the built-in viewpager in XML

<mypackage.CustomViewPager 
    android:id="@+id/myViewPager" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent" />

You just need to call the setPagingEnabled method with false and users won't be able to swipe to paginate.

GLee
  • 5,003
  • 5
  • 35
  • 39
Rajul
  • 5,906
  • 2
  • 22
  • 26
  • 3
    Works perfectly for a view that has several subviews where one uses horizontal scrolling (eg. AChartEngine chart). In my fragment I use a callback to my activity telling it to turn or off the paging depending on if the user touched (ACTION_MOVE) the chart or left it (ACTION_CANCEL). Thanks a lot! – riper Feb 14 '14 at 23:22
  • 1
    @Rajul hey great code snippet.How could this be modified so that it enables paging to the right and paging to the left respectively? – Libathos Mar 11 '14 at 13:44
  • this is how it should be done - enabled/disable it as you need – martyglaubitz Jul 21 '14 at 09:32
  • 37
    You can simplify your `onTouchEvent` and `onInterceptTouchEvent` methods with `return enabled && super.onTouchEvent(event);` – nbarraille Aug 16 '14 at 02:38
  • 7
    I would also recommend changing the name of field from "enabled" to "swipePageChangeEnabled" or something like that. A month after writing the code you'll hardly remember what "enabled" means, especially when your class is called "CustomViewPager", where it isn't clear what the customization is. That's also a matter of style, but style matters if you don't want to end up with unsupportable project, that is easier to rewrite completely than to fix it. – bytefu Apr 06 '15 at 09:07
  • 5
    Where do I call setPagingEnabled? ._. – Ntikki Nov 06 '15 at 14:24
  • 2
    @Ntikki, you may call `setPagingEnabled()` method after you declare your `ViewPager` like this: `CustomViewPager yourCustomViewPager = (CustomViewPager) findViewById(R.id.yourCustomViewPager); yourCustomViewPager.setPagingEnabled(false)` – blueware Oct 03 '16 at 11:53
  • 2
    Why are you returning `false` in `onTouchEvent()` and `onInterceptTouchEvent()`? This way touching the pager titles (or icons) will do the swipe. Return `true` instead to disable also that. – Alaa M. Oct 07 '16 at 09:12
  • 2
    after I setPagingEnabled() to true, all of the views inside the layout become non click able...it is just like there is a transparent wall overlay on top of the layout – Newbie Feb 08 '17 at 06:30
145

Now we no need to create custom ViewPager

A new ViewPager2 name View available in android

Vertical orientation support

  • ViewPager2 supports vertical paging in addition to traditional horizontal paging. You can enable vertical paging for a ViewPager2 element by setting its android:orientation attribute

Using XML

<androidx.viewpager2.widget.ViewPager2
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:orientation="vertical" />

Using code

To disable swiping in viewpager2 use

viewPager2.setUserInputEnabled(false);

To enable swiping in viewpager2 Use

viewPager2.setUserInputEnabled(true);

for more information check this

UPDATE

Community
  • 1
  • 1
AskNilesh
  • 67,701
  • 16
  • 123
  • 163
121

The simplest way is to setOnTouchListener and return true for ViewPager.

mPager.setOnTouchListener(new OnTouchListener()
    {           
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            return true;
        }
    });
Piyush
  • 18,895
  • 5
  • 32
  • 63
Wayne
  • 6,361
  • 10
  • 46
  • 69
  • 59
    Does not work sometimes. I'm using a ViewPager with a FragmentPagerAdapter and several Fragment . After setting OnTouchListener to pager, if I fling left, the UI will still move to left a little bit. – Chris.Zou Feb 26 '13 at 06:24
  • 17
    It works when you add `pager.setCurrentItem(pager.getCurrentItem());` before returning `true`. – dng Sep 18 '13 at 11:14
  • seems to work for me. To solve some layout glitches i have `public int getItemPosition(Object object) { return POSITION_NONE; }`in my adapter, which forces recreation of pages and maybe solving other problems too. – r-hold Apr 29 '14 at 22:35
  • 7
    This is a PARTLY working solution. Horizontal swipes are handled in some strange way. I tested this with a Drag'n Drop Gridview as part of a ViewPager. When dragging using this solution, dragging from left to right and right to left fails. Personally I find Rajul's approach the best. – Ton Snoei Dec 18 '14 at 14:03
  • On Android 6 (haven't tested on any other versions yet) if you click and drag left many times you can see the view pager swiping left. It is very funny. – Hola Soy Edu Feliz Navidad Mar 02 '20 at 14:20
62

Overriding only onTouchEvent and onInterceptTouchEvent is not sufficient in case you have ViewPager itself inside another ViewPager. Child ViewPager would steal horizontal scroll touch events from parent ViewPager unless it is positioned on its first / last page.

To make this setup work properly you need to override also the canScrollHorizontally method.

See LockableViewPager implementation below.

public class LockableViewPager extends ViewPager {

    private boolean swipeLocked;

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

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

    public boolean getSwipeLocked() {
        return swipeLocked;
    }

    public void setSwipeLocked(boolean swipeLocked) {
        this.swipeLocked = swipeLocked;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return !swipeLocked && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return !swipeLocked && super.onInterceptTouchEvent(event);
    }

    @Override
    public boolean canScrollHorizontally(int direction) {
        return !swipeLocked && super.canScrollHorizontally(direction);
    }

}
sidon
  • 1,434
  • 1
  • 17
  • 30
59

Better to declare it styleable, so you can change its property from xml:

private boolean swipeable;

public MyViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyViewPager);
    try {
        swipeable = a.getBoolean(R.styleable.MyViewPager_swipeable, true);
    } finally {
        a.recycle();
    }
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    return swipeable ? super.onInterceptTouchEvent(event) : false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    return swipeable ? super.onTouchEvent(event) : false;
}

And in your values/attr.xml:

<declare-styleable name="MyViewPager">
  <attr name="swipeable" format="boolean" />
</declare-styleable>

so that you can use it in you layout xml:

<mypackage.MyViewPager
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/viewPager"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:swipeable="false" />

Of course, you can still have a get/set property.

Pietro
  • 591
  • 4
  • 4
38

If you are extending from ViewPager, you must also override executeKeyEvent as indicated previously by @araks

@Override
public boolean executeKeyEvent(KeyEvent event)
{
    return isPagingEnabled ? super.executeKeyEvent(event) : false;
}

Because some devices like the Galaxy Tab 4 10' show these buttons where most devices never show them:

Keyboard buttons

Grease
  • 1,308
  • 11
  • 12
33

To disable swipe

mViewPager.beginFakeDrag();

To enable swipe

mViewPager.endFakeDrag();
Piyush
  • 18,895
  • 5
  • 32
  • 63
KAMAL VERMA
  • 675
  • 7
  • 10
  • 24
    It's not a good solution because it allows small portions of movement, at least in my app. – koras Jun 05 '16 at 20:36
16

I needed to disable swiping on one specific page, and give it a nice rubber-band animation, here's how:

    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageScrolled(int position, float positionOffset,
                                   int positionOffsetPixels) {
            if (position == MANDATORY_PAGE_LOCATION && positionOffset > 0.5) {
                mViewPager.setCurrentItem(MANDATORY_PAGE_LOCATION, true);
            }
        }
Oded Breiner
  • 28,523
  • 10
  • 105
  • 71
  • It waits until the next page is partly visible. A code for the next page in `onPageSelected` will be executed. Even the next page will switch. So, this code doesn't do needed. – CoolMind Dec 13 '18 at 16:41
14

I wrote a CustomViewPager with a swiping control:

public class ScrollableViewPager extends ViewPager {
    private boolean canScroll = true;
    public ScrollableViewPager(Context context) {
        super(context);
    }
    public ScrollableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public void setCanScroll(boolean canScroll) {
        this.canScroll = canScroll;
    }
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return canScroll && super.onTouchEvent(ev);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return canScroll && super.onInterceptTouchEvent(ev);
    }
}

If you set canScroll to true, this ViewPager can be swiping with finger, false on the contrary.

I use this in my project, and it works great until now.

L. Swifter
  • 3,179
  • 28
  • 52
  • 2
    What if i have a button inside the ViewPager and i want the click? this solution stops everything below viewpager to be clicked.. – aimiliano Apr 07 '17 at 20:30
  • I did not have the issue that @aimiliano had. I have multiple clickable items in my ViewPager and that all worked fine with this solution. This worked perfectly for me! – Randy Jun 17 '20 at 19:49
14

If your are using ViewPager2 you just have to use:

viewpager.setUserInputEnabled(false);

From the docs:

Enable or disable user initiated scrolling. This includes touch input (scroll and fling gestures) and accessibility input. Disabling keyboard input is not yet supported. When user initiated scrolling is disabled, programmatic scrolls through setCurrentItem still work. By default, user initiated scrolling is enabled.

Thanks to: https://stackoverflow.com/a/61685871/9026710

Tayyab Mazhar
  • 1,560
  • 10
  • 26
12

I know it's mighty late to post this but here's a tiny hack to achieve your outcome ;)

Simply add a dummy view below your viewpager:

<android.support.v4.view.ViewPager
     android:layout_width="match_parent"
     android:layout_height="match_parent">
</android.support.v4.view.ViewPager>

<RelativeLayout
     android:id="@+id/dummyView"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
</RelativeLayout>

Then add a OnClickListener to your RelativeLayout.

dummyView = (RelativeLayout) findViewById(R.id.dummyView);

dummyView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
         //Just leave this empty
    }
});

Get a bit creative with layouts, their placements and their behaviour and you'll learn to find a way to do absolutely anything that you imagine :)

Good luck!

Piyush
  • 18,895
  • 5
  • 32
  • 63
Jay
  • 4,873
  • 7
  • 72
  • 137
  • An easier way is use `setClickable` instead of `setOnClickListener`, if you don't need to handle `onClick` event. – Chaos Feb 19 '17 at 15:25
  • 2
    wouldn't this also block touches within the viewpager? – android developer May 21 '17 at 10:41
  • Yes it will. It's the expected behaviour required by OP @androiddeveloper – Jay May 23 '17 at 02:42
  • @RickGrimesTheCoder I don't think you understood my question. I mean views within the viewpager's fragments. Will they still be touchable? – android developer May 23 '17 at 05:08
  • No they will not be since the viewpager itself has a click listener. This is only suitable for instances where you don't have interactive elements within the fragments. For example a Welcome ViewPager that changes its fragments dynamically @androiddeveloper – Jay May 23 '17 at 07:36
9

in kotlin

viewPagerNavigation.isUserInputEnabled = false
MSohm
  • 815
  • 6
  • 11
jaitor
  • 109
  • 1
  • 3
7

I used this class with success. Overriding the executeKeyEvent is required to avoid swiping using arrows in some devices or for accessibility:

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;

public class ViewPagerNoSwipe extends ViewPager {
    /**
     * Is swipe enabled
     */
    private boolean enabled;

    public ViewPagerNoSwipe(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = false; // By default swiping is disabled
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return this.enabled ? super.onTouchEvent(event) : false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.enabled ? super.onInterceptTouchEvent(event) : false;
    }

    @Override
    public boolean executeKeyEvent(KeyEvent event) {
        return this.enabled ? super.executeKeyEvent(event) : false;
    }

    public void setSwipeEnabled(boolean enabled) {
        this.enabled = enabled;
    }

}

And in the xml call it like this:

<package.path.ViewPagerNoSwipe
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
madx
  • 6,723
  • 4
  • 55
  • 59
  • It works. Only swipe is disabled and clicking on a tab is enabled. AS warns that `performClick()` method is not overriden. – CoolMind Dec 14 '18 at 07:38
6

In Kotlin, my solution, combining above answers.

class CustomViewPager(context: Context, attrs: AttributeSet): ViewPager(context, attrs) {
    var swipeEnabled = false

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onTouchEvent(ev) else false
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onInterceptTouchEvent(ev) else false
    }

    override fun executeKeyEvent(event: KeyEvent): Boolean {
        return if (swipeEnabled) super.executeKeyEvent(event) else false
    }
}
Jeff Padgett
  • 2,380
  • 22
  • 34
6

In kotlin, we can solve this by creating a custom widget inheriting the ViewPager class and adding a flag value for controlling swipe behavior.

NoSwipePager.kt

class NoSwipePager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) {

    var pagingEnabled: Boolean = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onTouchEvent(event)
        } else false
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onInterceptTouchEvent(event)
        } else false
    }
}

In xml

<your.package.NoSwipePager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/tab_layout" />

Disable swiping programmatically. If kotlin-android-extensions plugin is applied in build.gradle, swiping can be disabled by writing below code.

view_pager.pagingEnabled = false

Otherwise we can disable swiping using code below:

val viewPager : ViewPager = findViewById(R.id.view_pager)
viewPager.pagingEnabled = false
Sagar Chapagain
  • 1,683
  • 2
  • 16
  • 26
  • 2
    Overriding `onInterceptTouchEvent()` will prevent child views to receive input. In most cases this is __not__ the intended behavior. – Alex Semeniuk Jul 16 '19 at 14:55
  • @AlexSemeniuk Had you observed any problem after implementing this? I had enabled swiping on recycler view items for some actions and it is working fine. So the implementation is working fine in my case. – Sagar Chapagain Jul 17 '19 at 04:42
  • Sagar Chapagain: or course, I did. Each of my pages contains custom view, which processes touches in various ways (including scrolling, dragging, single and long taps). Not calling `super.onInterceptTouchEvent(event)` results in these views not receiving any input (which is the documented purpose of `onInterceptTouchEvent` method). – Alex Semeniuk Jul 17 '19 at 11:08
  • If that is the case you should rather use child fragment and maintain backstack. – Sagar Chapagain Jul 17 '19 at 11:13
  • 1
    How is this relevant to the current question? Fragments are placed inside some containers (which are __Views__) and their own layout contains __Views__. No matter what content I have inside the ViewPager, I am still dealing with the fact that overriding `onInterceptTouchEvent()` method prevents it (content) from receiving input. – Alex Semeniuk Jul 17 '19 at 11:45
5

Try overriding and returning true from either onInterceptTouchEvent() and/or onTouchEvent(), which will consume touch events on the pager.

AdamK
  • 21,199
  • 5
  • 42
  • 58
2

None of the above code is working smoothly.i tried this

<HorizontalScrollView
                    android:id="@+id/horizontalScrollView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:fillViewport="true">

                    <android.support.v4.view.ViewPager
                        android:id="@+id/pager"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent" />
                </HorizontalScrollView>
1

Another easy solution to disable swiping at specific page (in this example, page 2):

int PAGE = 2;
viewPager.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
        if (viewPager.getCurrentItem() == PAGE) {
                viewPager.setCurrentItem(PAGE-1, false);
                viewPager.setCurrentItem(PAGE, false);
                return  true;
        }
        return false;
}
Ofir
  • 171
  • 1
  • 5
1

If you write an image gallery with ImageViews and ViewPager, that supports zoom and pan, see a simple solution described here: Implementing a zoomable ImageView by Extending the Default ViewPager in Phimpme Android (and Github sample - PhotoView). This solution doesn't work with ViewPager alone.

public class CustomViewPager extends ViewPager {
    public CustomViewPager(Context context) {
        super(context);
    }

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        try {
            return super.onInterceptTouchEvent(event);
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}
CoolMind
  • 26,736
  • 15
  • 188
  • 224
1
This worked for me

viewPager.setOnTouchListener(new View.OnTouchListener() {
                                         @Override
                                         public boolean onTouch(View v, MotionEvent event) {
                                             if (viewPager.getCurrentItem() == 0) {
                                                 viewPager.setCurrentItem(-1, false);
                                                 return true;
                                             }
                                             else if (viewPager.getCurrentItem() == 1) {
                                                 viewPager.setCurrentItem(1, false);
                                                 return true;
                                             }
                                             else if (viewPager.getCurrentItem() == 2) {
                                                 viewPager.setCurrentItem(2, false);
                                                 return true;
                                             }
                                             return true;
                                         }
                                     });
Princewill Iroka
  • 536
  • 1
  • 7
  • 17
1
* NonSwipebleViewPager for kotlin
    
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.animation.DecelerateInterpolator
import android.widget.Scroller
import androidx.viewpager.widget.ViewPager
import java.lang.reflect.Field


class NonSwipebleViewPager : ViewPager {
    constructor(context: Context?) : super(context!!) {
        setMyScroller()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs) {
        setMyScroller()
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean { 
        return false
    }

    override fun onTouchEvent(event: MotionEvent): Boolean { 
        return false
    }

    private fun setMyScroller() {
        try {
            val viewpager: Class<*> = ViewPager::class.java
            val scroller: Field = viewpager.getDeclaredField("mScroller")
            scroller.isAccessible = true
            scroller.set(this, MyScroller(context))
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    inner class MyScroller(context: Context?) :
        Scroller(context, DecelerateInterpolator()) {
        override fun startScroll(
            startX: Int,
            startY: Int,
            dx: Int,
            dy: Int,
            duration: Int
        ) {
            super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/)
        }
    }
}
Praful Parmar
  • 213
  • 2
  • 6
1

If you dont want any type of scroll horizontal or vertical from user fingers then you can try -

yourViewPager.isUserInputEnabled = false

use "isUserInputEnabled ".

0

If you want to implement the same for Android in Xamarin, here is a translation to C#

I chose to name the attribute "ScrollEnabled". Because iOS just uses the excat same naming. So, you have equal naming across both platforms, makes it easier for developers.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Support.V4.View;
using Android.Util;

namespace YourNameSpace.ViewPackage {

    // Need to disable swiping for ViewPager, if user performs Pre DSA and the dsa is not completed yet
    // http://stackoverflow.com/questions/9650265/how-do-disable-paging-by-swiping-with-finger-in-viewpager-but-still-be-able-to-s
    public class CustomViewPager: ViewPager {
        public bool ScrollEnabled;

        public CustomViewPager(Context context, IAttributeSet attrs) : base(context, attrs) {
            this.ScrollEnabled = true;
        }

        public override bool OnTouchEvent(MotionEvent e) {
            if (this.ScrollEnabled) {
                return base.OnTouchEvent(e);
            }
            return false;
        }

        public override bool OnInterceptTouchEvent(MotionEvent e) {
            if (this.ScrollEnabled) {
                return base.OnInterceptTouchEvent(e);
            }
            return false;
        }

        // For ViewPager inside another ViewPager
        public override bool CanScrollHorizontally(int direction) {
            return this.ScrollEnabled && base.CanScrollHorizontally(direction);
        }

        // Some devices like the Galaxy Tab 4 10' show swipe buttons where most devices never show them
        // So, you could still swipe through the ViewPager with your keyboard keys
        public override bool ExecuteKeyEvent(KeyEvent evt) {
            return this.ScrollEnabled ? base.ExecuteKeyEvent(evt) : false;
        }
    }
}

In .axml file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <YourNameSpace.ViewPackage.CustomViewPager
      android:id="@+id/pager"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@android:color/white"
      android:layout_alignParentTop="true" />
</LinearLayout>
Lepidopteron
  • 6,056
  • 5
  • 41
  • 53
0

here is my implementation
that if you want to disable the swipe animation you can you use the swipeListener left and right and still want the scroll by finger but without animation

1-Override Viewpager method onInterceptTouchEvent and onTouchEvent

2- create your own GestureDetector

3- detect the swipe gesture and use the setCurrentItem(item, false)

ViewPager

public class ViewPagerNoSwipe extends ViewPager {
    private final GestureDetector gestureDetector;
    private OnSwipeListener mOnSwipeListener;

    public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
        mOnSwipeListener = onSwipeListener;
    }

    public ViewPagerNoSwipe(@NonNull Context context) {
        super(context);
        gestureDetector = new GestureDetector(context, new GestureListener());

    }

    public ViewPagerNoSwipe(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        gestureDetector = new GestureDetector(context, new GestureListener());


    }

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        gestureDetector.onTouchEvent(ev);
        return false;
    }

    public class GestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeRight();
                        } else {
                            if(mOnSwipeListener!=null)
                                mOnSwipeListener.onSwipeLeft();
                        }
                        result = true;
                    }
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeBottom();
                    } else {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public interface OnSwipeListener {

         void onSwipeRight();

        void onSwipeLeft();

        void onSwipeTop();

        void onSwipeBottom();
    }
}

the when you are set up the ViewPager set the swipeListener

postsPager.setOnSwipeListener(new ViewPagerNoSwipe.OnSwipeListener() {
            @Override
            public void onSwipeRight() {

              postsPager.setCurrentItem(postsPager.getCurrentItem() + 1,false);

            }

            @Override
            public void onSwipeLeft() {

            postsPager.setCurrentItem(postsPager.getCurrentItem() - 1, false);

            }
             ...
           }
tamtom
  • 2,474
  • 1
  • 20
  • 33
0

I just customized the viewpager a little and disable swiping easily.

public class CustomViewPager extends ViewPager {

private boolean swipeLocked;

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

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

public boolean getSwipeLocked() {
    return swipeLocked;
}

public void setSwipeLocked(boolean swipeLocked) {
    this.swipeLocked = swipeLocked;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    return !swipeLocked && super.onTouchEvent(event);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    return !swipeLocked && super.onInterceptTouchEvent(event);
}

@Override
public boolean canScrollHorizontally(int direction) {
    return !swipeLocked && super.canScrollHorizontally(direction);
}
}
Shivam Yadav
  • 958
  • 11
  • 23
-2
shareViewPager?.setOnTouchListener(object :View.OnTouchListener{
            override fun onTouch(v: View?, event: MotionEvent?): Boolean {
                for (PAGE in 0..shareViewPager.adapter!!.count){
                    if (shareViewPager.currentItem==PAGE){
                        shareViewPager.setCurrentItem(PAGE-1,false)
                        shareViewPager.setCurrentItem(PAGE,false)
                    }}
                return true
            }

        })