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?
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.
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 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;
}
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.
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;
}
}
diffX
is always positive, so the method never returns true
. –
Bisson 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();
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;
}
You have to create your own ViewPager subclass and override the canScrollHorizontally function
© 2022 - 2024 — McMap. All rights reserved.
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