ViewPager are two ways to achieve unlimited carousel

To their advice: Although the wheel is useful, but the premise is the use of the wheel: If you do not package a number of complex functions, they will write with a fundamental way, or even the best wheel that is someone else, when their project experience and wheels not the same place, it can only do nothing or to change other people's source code, of course, be able to read the package to apply their knowledge and their own ideas wheels can easily change the source code that is the best and simple.

1. The realization of ideas

Two options:

(1) within getCount Adapter () method returns Integer.MAX_VALUE.

Prepend (2) in the list of the last data, the data is inserted in a first end of the list, causing a circular illusion

2. realization

2.1 a program: getCount () Returns Integer.MAX_VALUE

2.1.1 ViewPager infinite loop

In the method of the Adapter ViewPager getCount, the return Integer.MAX_VALUE a large number, theoretically unlimited slide. When displaying a complete list of the real cycle, and from 0 real position list display data, create the illusion of an infinite loop rotation. Because the first page can not be slid to the left ViewPager cycle, so we have to select the location provided by mViewPager.setCurrentItem (Integer.MAX_VALUE / 2), so that the beginning can slide to the left, but the first page so as to display the value% data number == 0. Because ANR happens when setCurrentItem () after setting Integer.MAX_VALUE, so here use a custom large number is better, here I was 500

//当前选中页
private int currentPosition;
//数据项个数
private List<Integer> itemList;

public static final int mLooperCount = 500;


//设置当前选中的item
currentPosition = getStartItem();
viewPager1.setCurrentItem(currentPosition1);

private int getStartItem() {
    if(getRealCount() == 0){
            return 0;
        }
    // 我们设置当前选中的位置为Integer.MAX_VALUE / 2,这样开始就能往左滑动
    // 但是要保证这个值与getRealPosition 的 余数为0,因为要从第一页开始显示
    int currentItem = getRealCount() * BannerAdapter.mLooperCount / 2;
    if(currentItem % getRealCount()  ==0 ){
        return currentItem;
    }
    // 直到找到从0开始的位置
    while (currentItem % getRealCount() != 0){
        currentItem++;
    }
    return currentItem;
}

//获取数据项个数
private int getRealCount() {
    return itemList == null ? 0 : itemList.size();
}
复制代码

Adapter simply getCount () can return Integer.MAX_VALUE (here we changed to a specific value), other operations are normal operation.

@Override
public int getCount() {
    return getRealCount() * mLooperCount;
}
复制代码

2.1.2 added carousel function

Handler using the method postDelayed

private Handler mHandler = new Handler();

@Override
protected void onResume() {
    super.onResume();
    //开始轮播
    mHandler.postDelayed(mLoopRunnable, mDelayedTime);
}

@Override
protected void onPause() {
    super.onPause();
    //停止轮播
    mHandler.removeCallbacks(mLoopRunnable);    
}
复制代码
private final Runnable mLoopRunnable = new Runnable() {
    @Override
    public void run() {
        if (mIsAutoPlay) {

            //方案一
            currentPosition1 = viewPager1.getCurrentItem();
            currentPosition1++;
            if (currentPosition1 == bannerAdapter.getCount() - 1) {		//滑到最后一个时
                currentPosition1 = 0;								  //切换到第0个
                viewPager1.setCurrentItem(currentPosition1, false);
                mHandler.postDelayed(this, mDelayedTime);
            } else {
                viewPager1.setCurrentItem(currentPosition1);
                mHandler.postDelayed(this, mDelayedTime);
            }            
        } else {
            mHandler.postDelayed(this, mDelayedTime);
        }
    }
};
复制代码

2.1.3 Integer.MAX_VALUE controversy

Some people may think it will affect memory, we can refer to this article Android ViewPager unlimited carousel Integer.MAX_VALUE controversy (see source code) will be able to solve doubts.

2.1.4 Note

Use Integer.MAX_VALUE ANR happens when setCurrentItem (), it is set to a larger number is better. In the code I've changed to return getRealCount () * 500 this value, if there is the return of Integer.MAX_VALUE that I did not correct, you change yourself article.

2.2 Option II: either end, two data items

2.2.1 ViewPager infinite loop

Suppose there are three data, numbered 1, 2, we'll create a new list, the length is the length of the list of real +2, inserted into the top of the last 3 data, insert data at the end of the first surface in 1, new list becomes 3,1,2,3,1, when slid to a position on viewpager by 0:00 setCurrentItem(int item,boolean smoothScroll)method to switch the page position 3, similarly to the position when the slide 4, the page is switched to position 1 by this method, so It gives us the feeling that an infinite loop.

private int currentPosition2;
private void initData2() {

    itemList2 = new ArrayList<>();
    itemList2.add(R.drawable.ic_pic4);
    itemList2.add(R.drawable.ic_pic1);
    itemList2.add(R.drawable.ic_pic2);
    itemList2.add(R.drawable.ic_pic3);
    itemList2.add(R.drawable.ic_pic4);
    itemList2.add(R.drawable.ic_pic1);

    bannerAdapter2 = new BannerAdapter2(itemList2);
    viewPager2.setAdapter(bannerAdapter2);
    currentPosition2 = 1;

    viewPager2.setCurrentItem(currentPosition2);

    viewPager2.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i1) {
        }

        @Override
        public void onPageSelected(int i) {
            currentPosition2 = i;
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            //验证当前的滑动是否结束
            if (state == ViewPager.SCROLL_STATE_IDLE) {
                if (currentPosition2 == 0) {
                    viewPager2.setCurrentItem(itemList2.size() - 2, false);//切换,不要动画效果
                } else if (currentPosition2 == itemList2.size() - 1) {
                    viewPager2.setCurrentItem(1, false);//切换,不要动画效果
                }
            }
        }
    });
}
复制代码

2.2.2 added carousel function

private Handler mHandler2 = new Handler();
@Override
protected void onResume() {
    super.onResume();
    //开始轮播
    mHandler2.postDelayed(mLoopRunnable2, mDelayedTime);
}

@Override
protected void onPause() {
    super.onPause();
    //停止轮播
    mHandler2.removeCallbacks(mLoopRunnable2);
}
复制代码
private final Runnable mLoopRunnable2 = new Runnable() {
    @Override
    public void run() {
        if (mIsAutoPlay) {
                //方案二:多添两条数据
                currentPosition2 = viewPager2.getCurrentItem();
                currentPosition2++;
                //不需要为了循环轮播来判断是否到达最后一页,在监听器中已经为我们做了此操作
                viewPager2.setCurrentItem(currentPosition2);
                mHandler2.postDelayed(this, mDelayedTime);

            } else {
                mHandler2.postDelayed(this, mDelayedTime);
            }
        }
};
复制代码

With a different program when slid into place is the last one, the switching to the next page labeled 1, when the slide page subscript 0 is switched to the last

2.3 Comparison of

Van't still dilute the West said of the article: The second option is switched animation, because when the position of the slide 4, we passed setCurrentItem (int item, boolean smoothScroll) method to switch it to position 1 only With infinite loop effect, but in order not to be found, and the second parameter smoothScroll set to false, so there is no switching animation, resulting in stiff, so do this.

Originally thought to achieve Option II (think of a way to be on the line), but curiosity made me want to see how stiff the next in the end, but did not find blunt the effect. Because we monitor the state of the end of the animation in onPageScrollStateChanged () method in, so when slid to fourth, again opened a period of time, we are actually slide into the fifth, that picture is that we add to the tail of this when there is a movie, not itemlist at index position 0, and in this listener, when it is judged in fact, the last one, we have passed setCurrentItem () mode without animated secretly switched to it subscript 1 position, so when the handler slide again by currentItem ++ way that it slides into the picture is labeled 2, also with effect, so what blunt the effect does not exist. Below I put a total of four maps, we can take a closer look at the effect of:

3. Summary

That's all for the most basic ways to achieve ViewPager unlimited carousel. See specific code Github .

In fact, we have a common view of Banner there Indicator indicator (that is, the bottom dots), which I actually used or still Van't dilute Western custom Indicator, because it really useful, and if the package is also very simple, although the same , but I still want to look at a re-recording process of the package so that they are under the impression deepened, see the next article.

4. Reference article

Android ViewPager unlimited carousel Integer.MAX_VALUE controversy (see source)

Advertising BannerView imitation Meizu applications ViewPager series

Android uses ViewPager unlimited carousel blank bug reasons and solutions (Integer.MAX_VALUE implementation)

Reproduced in: https: //juejin.im/post/5d08b8a251882559ed71d789

Guess you like

Origin blog.csdn.net/weixin_33889665/article/details/93179721