Is it possible to disable scrolling on a ViewPager
Asked Answered
O

16

155

I have a ViewPager which instantiates a View. I'd like to disable both the scrolling of the viewpager and the child buttons momentarily while a search result is returned to the view. I've calling viewPager.setEnabled(false) but this doesn't disable it.

Anyone got any ideas?

Osiris answered 18/10, 2011 at 21:32 Comment(1)
H
379

A simple solution is to create your own subclass of ViewPager that has a private boolean flag, isPagingEnabled. Then override the onTouchEvent and onInterceptTouchEvent methods. If isPagingEnabled equals true invoke the super method, otherwise return.

public class CustomViewPager extends ViewPager {

    private boolean isPagingEnabled = true;

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

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

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

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

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

Then in your Layout.XML file replace any <com.android.support.V4.ViewPager> tags with <com.yourpackage.CustomViewPager> tags.

This code was adapted from this blog post.

Hanky answered 18/10, 2011 at 21:36 Comment(10)
greate solution, works fine. If you want to stop swiping like a monkey you can override a OnPageChangeListener with @Override public void onPageScrollStateChanged(final int state) { switch (state) { case ViewPager.SCROLL_STATE_SETTLING: mPager.setPagingEnabled(false); break; case ViewPager.SCROLL_STATE_IDLE: mPager.setPagingEnabled(true); break; } // noop }Stiegler
P.S: In XML, use <yourpkgname.CustomViewPager... instead of <com.android,support.v4.ViewPager...Heurlin
to add another similar solution, you can use the library called "JazzyViewPager" : github.com/jfeinstein10/JazzyViewPager , and just call setPagingEnabled(boolean)Estes
is it possible to stop scrolling right only? i can scrolling left onlyToledo
It is still possible to "scroll" by focusing elements (buttons, etc.) in the pages when using a game controller or keyboard for instance. How to disable that completely? I guess it's another type of event that should be intercepted...Colophon
Yes, you must set the isPagingEnabled variable to false in the CustomViewPager class, change the tag in you layout .xml file to your CustomViewPager class ****AND**** in the .java file that you declare the view pager view, you must import the custom class, replace import android.support.v4.view.ViewPager; for import ******.CustomViewPager;Elvera
this will work, we can use this code into our custom viewYemane
Warning "Method 'setPagingEnabled(boolean)' is never used". Do I even need this code or can I delete it? Will anything be affected negatively if I do?Theine
Opposed to the beginFakeDrag() trick, this custom viewpager completely prevents its touch events. Great solution.Early
To prevent "scroll" by focusing elements with a controller or a keyboard just set: android:focusable="false" to all your views on the .xmlWivinia
Z
37

There is an easy fix for this one:

When you want to disable the viewpager scrolling then:

mViewPager.setOnTouchListener(new OnTouchListener() {

   public boolean onTouch(View arg0, MotionEvent arg1) {
      return true;
   }
}); 

And when you want to re-enable it then:

mViewPager.setOnTouchListener(null);

That will do the trick.

Zandrazandt answered 20/11, 2012 at 12:56 Comment(3)
Almost, but not quite. The touch down still happens, so you can move pages by doing lots of small swipes.Prizewinner
@Akhil Sekharan Was facing the problem exactly what Flynny is facing when using this answer.. but fortunately don't know how suddenly that error has gone.. :) and worked like a charm !!Cantatrice
You can do the lots of little swipes so you still have to over public boolean onInterceptTouchEvent(MotionEvent event) { ride as per slatons answerSarad
B
29

Here is my light weight variant of slayton's answer:

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

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

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

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

With my code you can disable the paging with setEnable().

Bausch answered 1/9, 2014 at 8:29 Comment(1)
Overriding onInterceptTouchEvent() will prevent child views to receive input. In most cases this is not the intended behavior.Denazify
D
24

In my case of using ViewPager 2 alpha 2 the below snippet works

viewPager.isUserInputEnabled = false

Ability to disable user input (setUserInputEnabled, isUserInputEnabled)

refer to this for more changes in viewpager2 1.0.0-alpha02

Also some changes were made latest version ViewPager 2 alpha 4

orientation and isUserScrollable attributes are no longer part of SavedState

refer to this for more changes in viewpager2#1.0.0-alpha04

Decompound answered 21/12, 2019 at 10:34 Comment(1)
The correct and working Answer for ViewPager2Smythe
F
20

I found a simple solution.

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();
Fecal answered 15/5, 2015 at 7:56 Comment(5)
Is this all the code you used? This is not working for me.Advisable
Doesn't work for me. Still can do lots of little swipes.Lemmuela
This code is not proper bcz It is scrolling very slowly like hanging viewShala
This may work by luck. Update to ViewPager can break this hack.Gibbon
It's still dragging but little by little ( .Morphogenesis
U
17

I suggest another way to solve to this problem. The idea is wrapping your viewPager by a scrollView, so that when this scrollView is non-scrollable, your viewPager is non-scrollable too.

Here is my XML layout:

        <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/viewPager"
                android:layout_width="wrap_content"
                android:layout_height="match_parent" />

        </HorizontalScrollView>

No code needed.

Works fine for me.

Upton answered 5/4, 2017 at 8:35 Comment(4)
Among all these answers, I feel this is simple and works just fine!!Eloiseelon
OK ... BUT when you have a map as one of the fragment in ViewPager then ... it's a problemMorphogenesis
@Morphogenesis You can move focus to your fragment, so scrolling will affect your map.Upton
Just one disadvantage, if you have another view pager in one of viewpager's fragment, then that viewpager also not getting swipeTarazi
J
5

To disable swipe

 mViewPager.beginFakeDrag();

To enable swipe

 mViewPager.endFakeDrag();
Jaundiced answered 1/3, 2017 at 6:37 Comment(2)
Scrolling is still possible, its just not fluent anymore. This is basically just worsending the quality without solving the problem.Ashleeashleigh
duplicated answerDecolorize
M
3

The best solution that worked for me is:

public class DeactivatedViewPager extends ViewPager {

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

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

    @Override
    public boolean canScrollHorizontally(int direction) {
        return false;
    }
}

After this the scroll will be disabled by touch and then you can still use setCurrentItem method to change page.

Malines answered 9/3, 2017 at 5:25 Comment(2)
Don't know why, but it simply didn't work. The scrolling still happens.Decolorize
The canScrollHorizontally() method has no effect in current scenario. It is not even called when swipe happens.Denazify
C
3

Here's an answer in Kotlin and androidX

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager

class DeactivatedViewPager @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : ViewPager(context, attrs) {

    var isPagingEnabled = true

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onInterceptTouchEvent(ev)
    }
}
Cedell answered 17/1, 2019 at 10:12 Comment(0)
B
2

How about this :
I used CustomViewPager
and next, override scrollTo method
I checked the movement when doing a lot of small swipes, it doesn't scroll to other pages.

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;
    } 

    @Override
    public void scrollTo(int x, int y) {
       if(enabled) {
          super.scrollTo(x, y);
       }
    }
}
Bustos answered 8/2, 2017 at 9:5 Comment(2)
I had the problem that the viewpager was still doing little swipes, but overriding View.scrollTo(int x, int y) solved this problem for me. ThanksJequirity
It causes some strange behavior in some cases. Like going to the void and leaving just a blank page '-'Decolorize
G
2
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);
}

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

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    // stop swipe 
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // stop switching pages
    return false;
}

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*/);
    }
}
}

Then in your Layout.XML file replace any --- com.android.support.V4.ViewPager --- tags with --- com.yourpackage.NonSwipeableViewPager --- tags.

Same solution but in Kotlin:

class NonSwipeableViewPager constructor(
    context: Context,
    attrs: AttributeSet?
) : ViewPager(context, attrs) {

    private var isPagingEnabled = true

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        return isPagingEnabled && super.onTouchEvent(event)
    }

    override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
        return isPagingEnabled && super.onInterceptTouchEvent(event)
    }

    fun setPagingEnabled(isEnabled: Boolean) {
        isPagingEnabled = isEnabled
    }
}
Gibber answered 3/2, 2019 at 11:48 Comment(0)
A
2

I created a Kotlin version based on converting this answer from Java: https://mcmap.net/q/64124/-how-do-disable-paging-by-swiping-with-finger-in-viewpager-but-still-be-able-to-swipe-programmatically

There is no built in way to disable swiping between pages of a ViewPager, what's required is an extension of ViewPager that overrides onTouchEvent and onInterceptTouchEvent to prevent the swiping action. To make it more generalised we can add a method setSwipePagingEnabled to enable/disable swiping between pages.

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

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return when (swipeEnabled) {
            true -> super.onTouchEvent(event)
            false -> false
        }
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return when (swipeEnabled) {
            true -> super.onInterceptTouchEvent(event)
            false -> false
        }
    }

    fun setSwipePagingEnabled(swipeEnabled: Boolean) {
        this.swipeEnabled = swipeEnabled
    }
}

Then in our layout xml we use our new SwipeLockableViewPager instead of the standard ViewPager

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

Now in our activity/fragment we can call myViewPager.setSwipePagingEnabled(false) and users won't be able to swipe between pages


UPDATE

As of 2020 we now have ViewPager2. If you migrate to ViewPager2 there is a built in method to disable swiping: myViewPager2.isUserInputEnabled = false

Almondeyed answered 2/11, 2020 at 22:22 Comment(0)
K
1

New class ViewPager2 from androidx allows to disable scrolling with method setUserInputEnabled(false)

private val pager: ViewPager2 by bindView(R.id.pager)

override fun onCreate(savedInstanceState: Bundle?) {
    pager.isUserInputEnabled = false
}
Kallick answered 23/8, 2019 at 17:0 Comment(0)
S
0

The answer of slayton works fine. If you want to stop swiping like a monkey you can override a OnPageChangeListener with

@Override public void onPageScrollStateChanged(final int state) { 
        switch (state) { 
            case ViewPager.SCROLL_STATE_SETTLING: 
                mPager.setPagingEnabled(false); 
                break; 
            case ViewPager.SCROLL_STATE_IDLE: 
                mPager.setPagingEnabled(true); 
                break; 
        } 
    }

So you can only swipe side by side

Stiegler answered 20/7, 2012 at 9:47 Comment(3)
I didn't found any method of ViewPager such as setPagingEnabled(boolean value)Cacka
setPagingEnabled(boolean value) is to be created by you,becoz there no such method to override.Skewbald
Unclear what this setPagingEnabled() method does. Please include the complete code.Denazify
A
0

In viewPager2 by disabling user input, you can prevent the user from swiping horizontally.

viewPager.isUserInputEnabled = false
Aviles answered 13/2, 2023 at 13:21 Comment(0)
C
0

This is working for me :- (for ViewPager2)

viewPager.isUserInputEnabled = false
Crass answered 22/3, 2023 at 5:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.