CQM
CQM

Reputation: 44220

Infinite viewpager with position indicator

Infinite looping viewpagers rely on an illusion where the count of items is increased to an arbitrarily large number, which are mapped via modulus to index positions in a list.

The problem with this being that indicators such as Circle page indicators get the arbitrarily long count of numbers, because they use the getCount() method of the host PagerAdapter, completely breaking down the illusion of infinite looping.

Ie. You have 3 items you want to loop through, you set the pageradapter count to 1000, when the user gets to item 3 and swipes to item "4", the item 1 shows again. But the indicator shows you are at item 4 and that there are hundreds of other items to swipe to. Instead of just looping between 3 indicator selections.

Is there a solution for this?

Upvotes: 1

Views: 5869

Answers (2)

amadeus
amadeus

Reputation: 41

I didn't want to spend time with new libraries. So, I code a simple OnPageChangeListener for infinite viewpagers with circle indicator (ImageView). It works well. AutoScrollViewPager is used as infinite viewPager. Indicator changes when viewpager scrolled half of the page not when scrolling is over.

Screenshot (circles are images is): enter image description here

Usage:

bannerPager.setOnPageChangeListener(new OnPageChangeListenerForInfiniteIndicator(getActivity(), bannerList, bannerPager.getCurrentItem()));

xml:

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/home_banner_indicator_container_height">

            <LinearLayout
                android:id="@+id/container_home_page_indicator"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_centerHorizontal="true"
                android:layout_marginBottom="@dimen/home_banner_indicator_container_inner_margin_vertical"
                android:layout_marginTop="@dimen/home_banner_indicator_container_inner_margin_vertical"
                android:orientation="horizontal">

            </LinearLayout>
        </RelativeLayout>

The OnPageChangeListenerForInfiniteIndicator:

import android.app.Activity;
import android.support.v4.view.ViewPager;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.kartaca.rbtpicker.R;
import com.kartaca.rbtpicker.model.Banner;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by amadeus on 9/18/15.
 */
public class OnPageChangeListenerForInfiniteIndicator implements ViewPager.OnPageChangeListener {
    private Activity activity;
    private List<ImageView> pageIndicatorList = new ArrayList<ImageView>();
    private List<Banner> bannerList;
    private LinearLayout containerIndicator;
    private int viewPagerActivePosition;
    private int positionToUse = 0;
    private int actualPosition;

    public OnPageChangeListenerForInfiniteIndicator(Activity activity, List<Banner> bannerList, int currentItem) {
        this.activity = activity;
        this.bannerList = bannerList;
        this.actualPosition = currentItem;
        this.viewPagerActivePosition = currentItem;
        loadIndicators();
    }

    private void loadIndicators() {
        containerIndicator = (LinearLayout) activity.findViewById(R.id.container_home_page_indicator);
        if (pageIndicatorList.size() < 1) {
            for (Banner banner : bannerList) {
                ImageView imageView = new ImageView(activity);
                imageView.setImageResource(R.drawable.banner_pagination_normal);// normal indicator image
                imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
                imageView.setLayoutParams(new ViewGroup.LayoutParams(activity.getResources().getDimensionPixelOffset(R.dimen.home_banner_indicator_width), 
            ViewGroup.LayoutParams.MATCH_PARENT));
                pageIndicatorList.add(imageView);
            }
        }
        containerIndicator.removeAllViews();
        for (int x = 0; x < pageIndicatorList.size(); x++) {
            ImageView imageView = pageIndicatorList.get(x);
            imageView.setImageResource(x == positionToUse ? R.drawable.banner_pagination_active :
         R.drawable.banner_pagination_normal); // active and notactive indicator
            containerIndicator.addView(imageView);
        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        actualPosition = position;
        int positionToUseOld = positionToUse;
        if (actualPosition < viewPagerActivePosition && positionOffset < 0.5f) {
            positionToUse = actualPosition % bannerList.size();
        } else {
            if (positionOffset > 0.5f) {
                positionToUse = (actualPosition + 1) % bannerList.size();
            } else {
                positionToUse = actualPosition % bannerList.size();
            }
        }
        if (positionToUseOld != positionToUse) {
            loadIndicators();
        }
    }

    @Override
    public void onPageSelected(int position) {

    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == 0) {
            viewPagerActivePosition = actualPosition;
            positionToUse = viewPagerActivePosition % bannerList.size();
            loadIndicators();
        }
    }
}

Upvotes: 1

Vadim Kotov
Vadim Kotov

Reputation: 8284

Take a look at InfinitePageIndicator project, maybe it is something that you need.

Upvotes: 0

Related Questions