Paginate Arraylist used in Viewpager android

242 Views Asked by At

I want to use Viewpager to show images like Whatsapp shows, when we click on any photo in any person chat then it would open the full screen imageview and we can scroll left or right to see more media items from that chat.

I know they might be using pagination to load more images on demand on both ends of the Viewpager, but thinking of it if we update the list dynamically when user is watching a photo in the Viewpager then won't he notice the updation of the Image Arraylist.

Whatsapp handles it very clearly.

What could be done to add more data to the arraylist dynamically without letting the user know, I am asking for pagination on both left and right ends not only one side.

1

There are 1 best solutions below

4
Håkon Schia On

I don't know how WhatsApp works, but if you want to have an "infinite" sliding ViewPager you can return a large value in getCount() and use modulo to get the correct image.

Something like:

public class ImageAdapter extends PagerAdapter {
    List<Image> images;
    
    public ImageAdapter(List<Image> images) {
        this.images = images;
    }

    @Override
    public int getCount() {
        return images.size() * 100;
    }

    @Override
    public Object instantiateItem(ViewGroup container, final int position) {
        Image image = images.get(position % images.size());

        // Instantiate your view
    }
}

And when you set your ViewPager set the current item to a large value as well so you can actually scroll both ways

viewPager.setCurrentItem(images.size() * 50)

This will probably have some impact on performance as more views will have to be created.

Option 2

Another option is to add a ViewPager.OnPageChangeListener that changes which item is the active one. You'll still have to return a larger value in getCount(), but it's only three times the size of the list, so it won't be as drastic.

The idea is to scroll to the "same" item which takes you to the middle of the list so it feels like you're infinitely scrolling

In the adapter:

// For a list with 2 items, the list will look like:
// 0 1    0 1    0 1

@Override
public int getCount() {
    return images.size() * 3;
}
// Set the first active item to be in the middle
//      Here
//        |
// 0 1    0 1    0 1
viewPager.setCurrentItem(images.size());

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    int currentPos;

    @Override
    public void onPageSelected(int position) {
        currentPos = position;
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            // Here       Go here    Or here
            //   |          |          |
            // 0 1        0 1        0 1
            if (currentPos == images.size() - 1 || currentPos == adapter.getCount() - 1) {
                // Scrolling with "false" removes the animation and instantly switches 
                // item, so you won't notice the scroll
                viewPager.setCurrentItem(images.size() * 2 - 1, false);
            } else if (currentPos == images.size() * 2 || currentPos == 0) {
                // Or here  Go here    Here
                // |          |          |
                // 0 1        0 1        0 1
                viewPager.setCurrentItem(images.size(), false);
            }
        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        // Not implemented
    }
});

The problem with this solution is that it's not guaranteed that onPageScrollStateChanged will be called with SCROLL_STATE_IDLE since you might scroll to a new page before it reaches the idle state, which causes you to scroll past the item where it should switch. If you reach the end/start it will change items, but you will notice you can't scroll for a short time if you're scrolling fast enough.

Neither of these options are perfect, but hopefully it will give you an idea of what is possible.