How Do Disable Paging by Swiping With Finger in Viewpager But Still Be Able to Swipe Programmatically

How do disable paging by swiping with finger in ViewPager but still be able to swipe programmatically?

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

How to disable ViewPager from swiping and enable manual swipe using button click

You can use ViewPager2 as mentioned in the comment above by https://stackoverflow.com/users/7725103/rajasekhar, but if you really need to use a viewpager: then you will have to create a custom viewpager like this:

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.viewpager.widget.ViewPager;

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

Usage

 <com.yourpackagename.CustomViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="@id/tab_layout"/>

Finally :
In the class you are using the viewpager:

 CustomViewPager viewPager=findViewById(R.id.view_pager);
viewPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});

This Solution is for those using ViewPager2

Set you Layout thus:

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/tab_layout"/>

And then set the class thus: No matter the way you code just placing this viewPager2.setUserInputEnabled(false); disables swiping effects

ViewPager2 viewPager2 = findViewById(R.id.viewPager);
viewPager2.setAdapter(new SimpleFragmentPagerAdapter(this));
viewPager2.setUserInputEnabled(false);

Goodluck!

How do I disable the swipe function in this particular viewpager?

You need to create a custom ViewPager that intercepts the onTouch events and avoid the default behaviour. This way the user wont be able to swipe between pages but will be able to touch on the tabs.

You can check this link where is already answered: How do disable paging by swiping with finger in ViewPager but still be able to swipe programmatically?

EDIT

I'll explain it by steps:

  1. Create a new class called NonSwipeableViewPager
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*/);
}
}
}

  1. Modify your layout to use the new ViewPager
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">


<android.support.design.widget.TabLayout
android:id="@+id/tabs"
app:tabGravity="fill"
app:tabMode="fixed"
android:background="@color/material_blue_grey_800"
app:tabIndicatorColor="@color/orange"
app:tabSelectedTextColor="@color/orange"
app:tabTextColor="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.design.widget.TabLayout>

<NonSwipeableViewPager <!-- You will need to import this correctly with your class package -->
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="50dp">

</NonSwipeableViewPager>



</LinearLayout>

  1. Update your activity with the new ViewPager
public class TabFragment extends Fragment {
public static TabLayout tabLayout;
public static NonSwipeableViewPager viewPager; // This line changed
public static int int_items = 2 ;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {


View x = inflater.inflate(R.layout.tab_layout,null);
tabLayout = (TabLayout) x.findViewById(R.id.tabs);
viewPager = (NonSwipeableViewPager) x.findViewById(R.id.viewpager); // This line changed

viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));

viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}



tabLayout.post(new Runnable() {
@Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});

return x;

}

You can keep the same adapter MyAdapter.

This will avoid the swipe between tabs but will keep the click on each one.

How to disable or enable viewpager swiping in android

Disable swipe progmatically by-

    final View touchView = findViewById(R.id.Pager); 
touchView.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
return true;
}
});

and use this to swipe manually

touchView.setCurrentItem(int index);

Disable swiping in ViewPager

In order to get something like this working, you will need to create your own subclass of ViewPager.

It should have a new field: e.g.

private boolean swipeEnabled;

You will also need to override onInterceptTouchEvent and onTouchEvent and check if the user has currently enabled / disabled the ViewPager.

e.g.

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

Then in your code where you are hosting your ViewPager you should have an enable and disable method that change the value of that new field based on your needs.

Make sure in your xml layout you use this new class rather than the default ViewPager class.

Disable View Pager swipe of Viewpager in Kotlin

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

Disable ViewPager Swipe

Just write;

viewPager = (CustomViewPager) findViewById(R.id.viewpager);

The findViewById method returns view, you have to say which class will be initialized.

How do disable paging by swiping with finger in ViewPager but still be able to swipe programmatically?

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



Related Topics



Leave a reply



Submit