天天看點

Android自定義控件--無限輪播Banner和Indicator實作

概述

應用首頁的廣告輪播

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資源。

Android自定義控件--無限輪播Banner和Indicator實作

測試

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();
           

最終效果圖

Android自定義控件--無限輪播Banner和Indicator實作

源碼:

AutoScrollLoopViewPager@[Github]