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?
This question is related to
android
android-viewpager
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);
}
}
}
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.
To disable swipe
mViewPager.beginFakeDrag();
To enable swipe
mViewPager.endFakeDrag();
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
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)
}
}
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()
.
I found a simple solution.
//disable swiping
mViewPager.beginFakeDrag();
//enable swiping
mViewPager.endFakeDrag();
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.
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.
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
}
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
I created a Kotlin version based on converting this answer from Java: https://stackoverflow.com/a/13437997/8023278
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
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.
Source: Stackoverflow.com