天天看點

Android小技巧之無限循環的ViewPager

前言

之是以會寫着篇文章的原因是我現在項目用運用到了廣告輪播(BannerView),當時在趕項目的時候在github上面找到了符合的開

源庫 就直接引用了,但是該開源庫稍微有點龐大,功能比較繁多。于是在這樣的情況之下,我決定自己造輪子。(現在處于項目完善和疊代器,正在重構項目,去除多餘的第三方等以減少APK的大小,增加使用者的體驗度)

效果圖如下,為了錄制效果,是以将速度加快了。

Android小技巧之無限循環的ViewPager

輪播圖

Step1

在這期間碰到的第一個難點就是ViewPager的無縫循環,于是乎在各種谷歌之下發現都是千篇一律的代碼之後依然投入了

stackoverflow

的懷抱,最終找到了解決無縫循環的兩種方式:

第一種:

左右各增加一個頁面,造成無縫的假象

第二種:

getcount的時候傳回Integer.MAX_VALUE,這種方式會建立大量的對象,對于我來說不可取。

Step2

第一種方法實作起來非常的簡單,其原理是在Adapter裡面實作OnPageChangeListener接口,重寫onPageSelected來搞定,假如我有三個頁面需要互相切換:

A<->B<->C
           

隻要在初始化資料的時候在A的前面加上C,C的後面加上A現在就變成了3+2五個頁面:

C<->A<->B<->C<->A
           

這時候在重寫onPageSelected方法,目前的position為0的時候,setCurrentItem為(getCount-2),假如目前的position==4(getCount-1),就setCurrentItem為1:

int pageCount = getCount();
if (position == 0) {
    pager.setCurrentItem(pageCount - 2, false);
} else if (position == pageCount - 1) {
    //延時切換,避免閃爍
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            pager.setCurrentItem(1, false);
        }
    },600);
}
           

裡面我寫了一個匿名内部類,為了友善才這麼寫,至于為什麼需要延遲?注釋了試試就知道了。

Step3

完整代碼如下:

/***
 * BannerAdapter
 * @param <T>
 */
public class BannerAdapter<T> extends PagerAdapter {
    private List<T> mDatas;
    private Context mContext;
    private int count;

    public BannerAdapter(final ViewPager pager, List<T> mDatas, Context mContext) {
        super();
        this.mBannerHelper = mBannerHelper;
        this.mContext = mContext;
        int actualNoOfIDs = mDatas.size();
        count = actualNoOfIDs + 2;

        T t = mDatas.get(0);//擷取到第一個
        T t1 = mDatas.get(mDatas.size() - 1);//擷取到最後一個

        this.mDatas = mDatas;
        this.mDatas.add(mDatas.size(), t);
        this.mDatas.add(0, t1);

        pager.addOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                int pageCount = getCount();
                if (position == 0) {
                    pager.setCurrentItem(pageCount - 2, false);
                } else if (position == pageCount - 1) {
                    //延時切換,避免閃爍
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            pager.setCurrentItem(1, false);
                        }
                    },600);
                }
            }

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
    }

    public int getCount() {
        return count;
    }

    public Object instantiateItem(View container, int position) {
        View view;
        //TODO 在這裡傳回你的View
        ((ViewPager) container).addView(view, 0);
        return view;
    }

    @Override
    public void destroyItem(View container, int position, Object object) {
        ((ViewPager) container).removeView((View) object);
    }

    @Override
    public void finishUpdate(View container) {
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
    }

    @Override
    public Parcelable saveState() {
        return null;
    }

    @Override
    public void startUpdate(View container) {
    }
}
           

最後

最近在學習自定義View,感覺進度十分的緩慢,不過剛看到幾個UI互動效果,準備自己實作試試,挑戰自我。

源碼

繼續閱讀