Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ViewPager scrolling issue with only one item when using getPageWidth from PagerAdapter

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?

like image 699
Alvaro Luis Bustamante Avatar asked Aug 27 '13 09:08

Alvaro Luis Bustamante


People also ask

Is ViewPager deprecated?

This function is deprecated.

How do I stop ViewPager swiping?

To enable / disable the swiping, just overide two methods: onTouchEvent and onInterceptTouchEvent . Both will return "false" if the paging was disabled. You just need to call the setPagingEnabled method with false and users won't be able to swipe to paginate.

How do I scroll in ViewPager?

One should use ViewPager2 and in its XML set android:orientation="vertical" property and your ViewPager will scroll vertically. The complete code will be like this.

Can I use ViewPager with views not with fragments?

yes...you can use View instead of Fragment in viewpager.


3 Answers

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.

  1. 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;
        }
    }
    
  2. In your layout xml, replace your com.android.support.v4.ViewPager elements with com.yourpackage.MyViewPager elements.

  3. 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);
    
like image 182
rarp Avatar answered Oct 08 '22 12:10

rarp


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.

like image 29
barbucha Avatar answered Oct 08 '22 12:10

barbucha


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;  
}
like image 28
Mightian Avatar answered Oct 08 '22 10:10

Mightian