Android真正意義上的無限輪播Banner和Indicator


概述

  應用首頁的廣告輪播Banner,一般都會使用ViewPager來實現,但是ViewPager 沒有輪播效果。
現成有這么幾種實現方案,
  1.使用Integer.MAX_VALUE ,理論上很難達到邊界。
  2.裝飾adapter方式[imbryk/LoopingViewPager@Github]
  3.擴展ViewPager方式[yanzm/LoopViewPager]。 

相關庫

  輪播效果其實就是一個定時任務,可以用定時器,Handler等。

[Trinea/Android Auto Scroll ViewPager@Github]

此庫通過handler定時發送消息實現,用的比較多,使用中感覺切換並非無縫。主要代碼如下: 

/** * scroll only once */ 
public void scrollOnce() {
   PagerAdapter adapter = getAdapter(); 
  int currentItem = getCurrentItem(); 
  int totalCount; 
if (adapter == null || (totalCount = adapter.getCount()) <= 1) { 
  return; 
}
int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
if (nextItem < 0) {
  if (isCycle) {
    setCurrentItem(totalCount - 1, isBorderAnimation);
  }
} else if (nextItem == totalCount) {
  if (isCycle) {
    setCurrentItem(0, isBorderAnimation);
  }
} else {
    setCurrentItem(nextItem, true);
    }
}

  

這里是在最后或第一頁直接setCurrentItem(),因此,並非無縫輪播效果。

和本文開頭的幾個控件整合一下,即可方便 的實現我們想要無縫 的效果。 

基本實現

1.修改[Trinea/Android Auto Scroll ViewPager@Github]

改變首頁和最后一頁的跳轉設置。 

    /**
     * scroll only once
     */
    public void scrollOnce() {
        PagerAdapter adapter = getAdapter();
        int currentItem = getCurrentItem();
        if (adapter == null || adapter.getCount() <= 1) {
            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 == 0) return 0; 
int realPosition = (position-1) % realCount; 
if (realPosition < 0) realPosition += realCount; 
return realPosition; 
}

  

這里,內部封裝position映射,不需要自己處理position,和正常ViewPager使用方式一樣。

第三種,重寫擴展ViewPager 繼承 ViewGroup,使其item無限。需要自己處理position,而且 和 [JakeWharton/ViewPagerIndicator@Github]搭配使用起來不是很方便,setViewPager方法需要額外處理。

綜上,使用第二種方式 擴展性和 易用性都比較好。 

 

Indicator

[JakeWharton/ViewPagerIndicator@Github]
這是一個比較全面的indicator,如果我們只需要簡單的CircleIndicator,可以抽取來使用。

優秀相關開源庫:
[THEONE10211024/CircleIndicator@Github]
[ongakuer/CircleIndicator@Github]

也可以看看本人站在巨人肩膀上完成的[DrawableIndicator@Github]
實時偏移,切換動畫,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]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM