I am facing a problem on disabling the swipe gesture on viewpager fragment. Right now, I am using custom viewpager to disable the swipe gesture.
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) {
// Never allow swiping to switch between pages
return false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
}
As result, this also will disable pagerTitleStrip. The reason I need to disable swipe gesture as one of my fragment contains a feature to remove item by swiping. It is possible to disable swipe only on viewpager but not on pagerTitleStrip?
PagerTitleStrip only shows title.
use PagerTabStrip instead of PagerTitleStrip.
Related
This question already has answers here:
How do disable paging by swiping with finger in ViewPager but still be able to swipe programmatically?
(27 answers)
Closed 6 years ago.
In my android application, I have a viewpager which have a list of imageView. Each of the view can be drawn. When I draw on it, I can still swipe to the next view from viewpager. How can I disable the paging while user start to draw on a an imageView.
Add this as a class and use it in xml instead of your viewpager tag. Basically we make a customised viewpager, where we are disabling the swipeable behaviour by returning false to onInterceptTouchEvent and OnTouchEvent.
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) {
// Never allow swiping to switch between pages
return false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
}
I have 2 view pagers in a linear layout both taking up same amount of screen. I want to make it so that if a user swipes any where on the screen then the swipe should only be for the lower viewpager. I tried increasing the touch delegate but that didn't work.
Well you're trying to some trippy stuff! I'd suggest making a CustomViewPager class for the 2nd viewpager which can have an instance of the 1st viewPager.
public class CustomViewPager extends ViewPager {
private ViewPager firstViewPager;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(firstViewPager!=null){
firstViewPager.onTouchEvent(event);
}
return super.onTouchEvent(event);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if(firstViewPager!=null){
firstViewPager.onInterceptTouchEvent(event);
}
return super.onInterceptTouchEvent(event);
}
public void setFirstViewPager(ViewPager firstViewPager) {
this.firstViewPager = firstViewPager;
}
}
In this you are passing the motion event that you get in the 2nd viewpager's onTouchEvent and onInterceptTouchEvent to the 1st viewpager. You'd also want to disable the swipe on the 1st viewpager that you could do as described here.
I would like to disable the tab click / touch event on my PagerTabStrip. Basically I only want users to be able to swipe. I want the appearance of the tabs, but no touching/clicking events. I'm not sure if there is something configurable in the xml below. Or if there is something in code that I can do. I've tried overriding the strip's ontouch and onclick listeners. but no luck.
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/myId">
<android.support.v4.view.PagerTabStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:id="#+id/tabStripID"
android:background="#color/dark_blue"
android:textColor="#color/text"/>
</android.support.v4.view.ViewPager>
Overriding the onClick listener on PagerTabStrip does nothing because the onClick listeners are actually on two TextViews (the text for the previous and next tabs) contained within the PagerTabStrip class, and there is currently no API on PagerTabStrip to directly access/override those listeners. The following is solution that gets around this problem (and also doesn't get into the weeds of the internal PagerTabStrip implementation).
I verified that the following works:
Create your own PagerTabStrip and consume the touch event in onInterceptTouchEvent() by returning true. This will prevent either of the PagerTabStrip's internal onClick listeners from receiving touch event and doing the tab switch.
public class MyPagerTabStrip extends PagerTabStrip {
private boolean isTabSwitchEnabled;
public MyPagerTabStrip(Context context, AttributeSet attrs) {
super(context, attrs);
this.isTabSwitchEnabled = true;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.isTabSwitchEnabled) {
return super.onInterceptTouchEvent(event);
} else {
return true;
}
}
public void setTabSwitchEnabled(boolean isSwipeEnabled) {
this.isTabSwitchEnabled = isSwipeEnabled;
}
}
I assume that you'll also want to disable the ViewPager swiping that would also result in a tab switch. The following code does that (here, you have to return false in onTouch() and onInterceptTouch() instead of true to allow normal touch events to reach your current tab fragment):
public class MyViewPager extends ViewPager {
private boolean isSwipeEnabled;
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.isSwipeEnabled = true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.isSwipeEnabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.isSwipeEnabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean isSwipeEnabled) {
this.isSwipeEnabled = isSwipeEnabled;
}
}
Remember to change the XML file to reference these new classes:
<com.mypackage.MyViewPager
...
<com.mypackage.MyPagerTabStrip
...
Answer of Steve B is almost working, only the onTouchEvent() override is missing from the TabStrip (the same as for the viewpager). Without it it still receives the clicks and change page (at least on Android L).
I have a ViewPager with a custom PagerAdapter that overwrites the method getPageWidth to return 0.3f, so I can show multiple pages in the screen, as suggested in the following blog:
http://commonsware.com/blog/2012/08/20/multiple-view-viewpager-options.html
In this case the ViewPager starts empty and the user starts filling the pages (images) as requested. The images are filled from left to right. All is working fine and the pages are dinamically created, and it is easy to swipe between them when there are multiple images.
However there is a problem when there are less than three pages instantiated. A swipe gesture from right (no content) to left produces a flickering with pages moving from left to right alternatively, as if the ViewPager were trying to move the first pages to right but later turning to its original position. This happens during the whole gesture, and stop when leaving the gesture. As I said this does not happen when there are pages enough to cover the whole screen width and a real scroll is necessary.
Any Ideas?
I know this is an old question, but I was just looking for a solution and came across this link (which oddly references this question). Anyway, I was able to figure out a solution based on their comments. The basic idea is to allow touch events based on the state of a boolean flag which you set.
Extend ViewPager on override onInterceptTouchEvent & onTouchEvent to only call super if you've set the flag. My class looks like this:
public class MyViewPager extends ViewPager {
private boolean isPagingEnabled = false;
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyViewPager(Context context) {
super(context);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (isPagingEnabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (isPagingEnabled) {
return super.onTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean pagingEnabled) {
isPagingEnabled = pagingEnabled;
}
}
In your layout xml, replace your com.android.support.v4.ViewPager elements with com.yourpackage.MyViewPager elements.
Since you return 0.3f from getPageWidth() in your pager adapter, you would want scrolling enabled when the fourth item has been added to it. The tricky part is having this line of code everywhere when you define your pager adapter, and add or remove any objects from the adapter backing list.
mPager.setPagingEnabled(items.size() > 3);
Rahuls solution works, but if you want auto enabling of paging according to content, you can modify ViewPager like this:
public class MyViewPager extends ViewPager {
public MyViewPager(Context context,
AttributeSet attrs) {
super(context, attrs);
}
public MyViewPager(Context context) {
super(context);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (canScrollHorizontally(1)||canScrollHorizontally(-1)) {
return super.onInterceptTouchEvent(event);
}
return false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (canScrollHorizontally(1)||canScrollHorizontally(-1)) {
return super.onTouchEvent(event);
}
return false;
}
}
Now, if the ViewPager is scrollable, it will allow touches, otherwise disable.
I was able to solve it this way, in your getPageWidth() method,if there is only one image[you can get to know by checking size of array or arraylist] return 1, if the input size is greater than 1 return your decimal.
Here's the code to achieve this.
#override
public float getPageWidth(int position){
if(inpputsize==1){
return 1.0;
}
return 0.9;
}
I need to limit the swipe area inside a ViewPager. For example, if the user make the gesture to swipe on top half space of the screen it swipe to the next fragment, but if the user make the gesture on the bottom half of the screen it do nothing.
There is a way to do that?
This might be a what you need:
public class MyPager extends ViewPager {
public MyPager(Context context) {
super(context);
}
public MyPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(inNeutralArea(ev.getX(),ev.getY())){
//--events re-directed to this ViewPager's onTouch() and to its child views from there--
return false;
}else {
//--events intercepted by this ViewPager's default implementation, where it looks for swipe gestures--
return super.onInterceptTouchEvent(ev);
}
}
private boolean inNeutralArea(float x, float y) {
//--check if x,y inside non reactive area, return true/false accordingly--
return false;
}
}
Use this MyPager class in layout xml in place of ViewPager.
Don't forget to do to the same in overriding the onTouchEvent, otherwise the ViewPager will still scroll on Android 4.1 and later. Caught me ofguard and took me a while to figure it out.