概述
應用首頁的廣告輪播
Banner
,一般都會使用
ViewPager
來實作,但是
ViewPager
沒有輪播效果。
現成有這麼幾種實作方案,
1.使用
Integer.MAX_VALUE
,理論上很難達到邊界。
2.裝飾
adapter
方式[imbryk/[email protected]]。
3.擴充
ViewPager
方式[yanzm/LoopViewPager]。
相關庫
輪播效果其實就是一個定時任務,可以用定時器,
Handler
等。
[Trinea/Android Auto Scroll [email protected]]
此庫通過
handler
定時發送消息實作,用的比較多,使用中感覺切換并非無縫。主要代碼如下:
/**
* scroll only once
*/
public void scrollOnce() {
PagerAdapter adapter = getAdapter();
int currentItem = getCurrentItem();
int totalCount;
if (adapter == null || (totalCount = adapter.getCount()) <= ) {
return;
}
int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
if (nextItem < ) {
if (isCycle) {
setCurrentItem(totalCount - , isBorderAnimation);
}
} else if (nextItem == totalCount) {
if (isCycle) {
setCurrentItem(, isBorderAnimation);
}
} else {
setCurrentItem(nextItem, true);
}
}
這裡是在最後或第一頁直接
setCurrentItem()
,是以,并非無縫輪播效果。
和本文開頭的幾個控件整合一下,即可友善 的實作我們想要無縫 的效果。
基本實作
1.修改[Trinea/Android Auto Scroll [email protected]]
改變首頁和最後一頁的跳轉設定。
/**
* scroll only once
*/
public void scrollOnce() {
PagerAdapter adapter = getAdapter();
int currentItem = getCurrentItem();
if (adapter == null || adapter.getCount() <= ) {
return;
}
int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
setCurrentItem(nextItem, true);
}
2.實作方式選擇
第一種方式其實主要改變了
adapter
中的
index
,大體如下:
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
position = position % listviews.size() ;
//....
}
隻是理論上的無限,需要自己處理
position
。
第二種裝飾了
adapter
,在前後各添加一個
Item
,當到了我們添加的臨界
item
的時候,立即設定到正确的
position
,主要方法如下:
LoopPagerAdapterWrapper
:
int toRealPosition(int position) {
int realCount = getRealCount();
if (realCount == )
return ;
int realPosition = (position-) % realCount;
if (realPosition < )
realPosition += realCount;
return realPosition;
}
這裡,内部封裝
position
映射,不需要自己處理
position
,和正常
ViewPager
使用方式一樣。
第三種,重寫擴充
ViewPager
繼承
ViewGroup
,使其
item
無限。需要自己處理
position
,而且 和 [JakeWharton/[email protected]]搭配使用起來不是很友善,
setViewPager
方法需要額外處理。
綜上,使用第二種方式 擴充性和 易用性都比較好。
Indicator
[JakeWharton/[email protected]]
這是一個比較全面的
indicator
,如果我們隻需要簡單的
CircleIndicator
,可以抽取來使用。
優秀相關開源庫:
[THEONE10211024/[email protected]]
[ongakuer/[email protected]]
也可以看看本人站在巨人肩膀上完成的[[email protected]],
實時偏移,切換動畫,drawable資源。

測試
my_banner.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.bobomee.android.scrollloopviewpager.autoscrollviewpager.AutoScrollViewPager
android:id="@+id/picslooper1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.bobomee.android.drawableindicator.widget.DrawableIndicator
android:id="@+id/pageIndexor1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
app:indicator_height="15dp"
app:indicator_margin="15dp"
app:indicator_select_src="@drawable/select_drawable"
app:indicator_unselect_src="@drawable/unselect_drawable"
app:indicator_width="15dp" />
</RelativeLayout>
MainActivity:
AutoScrollViewPager viewPager = (AutoScrollViewPager) findViewById(R.id.picslooper1);
viewPager.setFocusable(true);
viewPager.setAdapter(new FragmentStateAdapter(getSupportFragmentManager()));
BaseIndicator pageIndex = (BaseIndicator) findViewById(R.id.pageIndexor1);
pageIndex.setViewPager(viewPager);
viewPager.startAutoScroll();
最終效果圖
源碼:
AutoScrollLoopViewPager@[Github]