Android App Banner,用它就夠了。無限輪播、簡單易用、擴展性強的BannerView

按照慣例先上效果圖:
引導頁效果
標題等信息跟隨頁面滾動
標題固定,圓點指示器
標題固定,數字指示器
還有各種效果

體驗Demo

點擊下載或掃碼下載DemoApk

"掃碼下載"

寫在前面

GitHub上有更加詳細的使用介紹的,如果你想直接看GitHub上的也可以直接點擊後面的傳送門去往GitHub。我是傳送門

本文的內容可能有點長,如果你想要直接但Demo的源碼的,可以直接跳到最後,最後有完整的代碼(包括Java代碼和XML代碼)。

前言

今天給大家推薦一款支持無限輪播的,簡單易用、擴展性強且超級穩定的輪播圖庫。

**·爲什麼說簡單易用?**答:因爲實現起來比較簡單,兩行代碼就可以輕鬆實現。

//找到控件。
BannerView bannerView = findViewById(R.id.vp_banner_view);
//設置數據源並啓動輪播。
bannerView.setEntries(entries, true);

**·爲什麼說擴展性強?**答:佈局樣式完全由自己決定,想怎麼佈局就怎麼佈局,我的原則是你的佈局你做主。如果你需要指示器你可以使用我提供的圓點型指示器也可以使用數字型指示器。什麼?都不喜歡?沒關係,你還可以實現Pageable接口或繼承BannerIndicator抽象類實現自己什麼腦洞打開的指示器都沒關係。什麼?不會寫自定義控件?沒關係可以使用任何第三方的或者任何類型的炫酷的NB的自定義控件作爲指示器,只是這時你需要對BannerView設置監聽,通過回調方法void onPageSelected(BannerEntry entry, int index)來爲你的自定義指示器設置指針。你想要自定義翻頁動畫?沒關係因爲這個庫是基於ViewPager實現的,所以你可以向使用ViewPager那樣對BannerView(ViewPager的子類)調用void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer)方法設置翻頁動畫。不瞭解PageTransformer的可以百度、google或則直接拷貝google官方文檔中的樣板,網上以大堆。注意,雖然BannerView是ViewPager的子類,但是依然支持改變翻頁動畫時長,依然支持自定義動畫差值器(可通過代碼和XML兩種方式實現)。

**·爲什麼說超級穩定?**答:大家都知道我們的輪播圖一般都是配合RecyclerView或ListView作爲它的一個Iitem使用的。但是VeiwPager在配合RecyclerView使用時有很多問題(ListView沒有驗證過不過根據Bug的原因推測也是有問題的)。比如,當ViewPager自動滑動到一半的時候,將其隱藏再顯示後,會出現無法自動滑完,動畫會在隱藏時的位置卡住,直到下一次自動輪播纔會恢復(只不過很多app的翻頁動畫時間過短,所以很難出現這種問題)。再比如,當ViewPager完全隱藏後再次顯示則在下一次輪播時沒有動畫。還有其他的問題就不一一贅述了(以上問題在市場上的很多app都存在。)。這些問題這個庫都解決了。(不知不覺寫了這麼多,是不是有點王婆賣瓜?)

下面進入正題

Gradle配置

首先要在你的Gradle中進行配置纔可以使用。

第一步:添加 JitPack 倉庫到你項目根目錄的 gradle 文件中。
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
第二步:添加這個依賴。
dependencies {
    implementation 'com.github.kelinZhou:Banner:2.5.6'
}

XML中使用

<com.kelin.banner.view.BannerView
    android:id="@+id/vp_view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:bannerIndicator="@+id/biv_indicator"
    app:titleView="@+id/tv_title"
    app:pagingIntervalTime="3000"
    app:singlePageMode="canNotPaging|noIndicator"
    app:decelerateMultiple="4"
    android:background="#FFF"/>

可以看到,基本所有的配置在佈局中都可以完成(當然,也提供了通過代碼配置的方法)。

指示器的使用

如果你需要指示器,本依賴庫默認提供了兩種指示器。你不需要在代碼中做任何事情,所有的配置都可以在XML中完成。

圓點型指示器在XML中的使用

<com.kelin.banner.view.PointIndicatorView
			android:id="@+id/biv_indicator"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			app:totalCount="4"
			app:pointRadius="3dp"
			app:selectedPointRadius="4dp"
			app:pointSpacing="4dp"
			app:pointColor="#5fff"
			app:selectedPointColor="@android:color/white"/>

數字型指示器在XML中的使用

<com.kelin.banner.view.NumberIndicatorView
           android:id="@+id/biv_indicator"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:textSize="16sp"
           android:textColor="@android:color/white"
           app:separator="/"
           app:separatorTextColor="@android:color/holo_green_light"
           app:currentPageTextColor="@android:color/white"
           app:totalPageTextColor="@android:color/white"
           app:totalCount="6"/>

BannerView的自定義屬性

app:pagingIntervalTime翻頁間隔時長,用來配置每次自動翻頁之間所間隔的時間,單位爲毫秒。例如你想每5秒自動翻頁一次,那麼該屬性應該爲5000。

app:decelerateMultiple翻頁動畫減速倍數,因爲BannerView是繼承自ViewPager,所以每次自動翻頁所需要的時長都是較短的,你可以通過設置該屬性來配置減速倍數,也就是你希望每次自動翻頁所需要的時長是ViewPager原時長的多少倍。

app:bannerIndicator爲BannerView指定指示器,只要是實現了Pageable接口的View都可以,該庫中所提供的所以指示器都實現了Pageable接口,如果你不滿足於我提供的指示器控件,那麼你可以自己動手寫只要實現Pageable接口就可以配合BannerView使用。例如樣例中的該屬性的值爲:@+id/biv_indicator

app:titleView爲BannerView指定用來顯示標題的控件,通過該屬性配置標題控件後你就不需要監聽BannerView的切換,然後再爲標題控件賦值。只要你配置了該屬性我會自動爲你賦值。前提是你要配置的控件必須是TextView或其子類。例如樣例中的該屬性的值爲:@+id/tv_title

app:subTitleView爲BannerView指定用來顯示副標題的控件,通過該屬性配置標題控件後你就不需要監聽BannerView的切換,然後再爲副標題控件賦值。只要你配置了該屬性我會自動爲你賦值。前提是你要配置的控件必須是TextView或其子類。例如該屬性的值爲:@+id/tv_sub_title

app:interpolator翻頁動畫差值器,可以通過該屬性配置自動翻頁動畫的動畫差值器。例如該屬性的值爲:@android:anim/bounce_interpolator

app:singlePageMode因爲支持無限輪播,那麼只有一張圖片的時候是否還需要無限輪播?這個屬性就是用來配置當Banner中的圖片只有一張時的處理方式的。該屬性是一個flag屬性,一共有以下兩個值:

  1. noIndicator表示如果只有一張圖片則沒有指示器。也就是說無論你是否設置了指示器,如果只有一張圖片的話那麼指示器都是不顯示的。但是依然是支持無限輪播的。

  2. canNotPaging表示如果只有一張圖片則不可以輪播。但是如你設置了指示器的話,指示器依然會顯示。

    上面兩個屬性可以同時配置,中間用"|"符號鏈接,例如上面代碼中的配置。這樣的話如果只有一張圖片則既不會輪播而且無論你是否設置了指示器則都不會顯示。

    以上所說的只有一張圖片是指通過BannerViewsetEntries方法設置數據源時數據源集合的size()等於1。所說的設置只是器是指在XML代碼中爲BannerView配置app:bannerIndicator屬性或者通過代碼BannerView.setIndicatorView(@NonNull BannerIndicator indicatorView)爲BannerView設置指示器。

app:loopMode配置輪播模式,該屬性爲枚舉屬性,有以下三個值可以配置:

  1. infiniteLoop無限循環輪播。
  2. fromCoverToCover從第一頁輪播到最後一頁,然後停止輪播。
  3. fromCoverToCoverLoop從第一頁輪播到最後一頁,然後再會到第一頁後再輪播到最後一頁,一直重複。

app:touchPauseEnable用來配置觸摸暫停輪播是否可用,BannerView默認在被觸摸時是會暫停自動輪播的,如果你不希望在BannerView被觸摸後被暫停自動輪播這可以爲該屬性賦值爲:false

PointIndicatorView的自定義屬性

app:totalCount一共有多少個點(也就是總頁數),如果是配合BannerView使用的則以BannerView的頁數爲準。這個屬性最大的用途就是在寫佈局文件時可以及時看到效果,方便調試UI。

android:gravity設置偏移。只支持以下值的單一配置及合理組合:

Gravity.TOP、Gravity.BOTTOM、View.NO_IDGravity.LEFT、View.NO_IDGravity.RIGHT、View.NO_IDGravity.START、View.NO_IDGravity.END、View.NO_IDGravity.CENTER、View.NO_IDGravity.CENTER_VERTICAL、View.NO_IDGravity.CENTER_HORIZONTAL。

可以同時配置多個值,多個值之間用"|"(或)符號連接。但是不支持View.NO_IDGravity#FILL、View.NO_IDGravity#FILL_VERTICAL、View.NO_IDGravity#RELATIVE_HORIZONTAL_GRAVITY_MASK、以及View.NO_IDGravity#FILL_HORIZONTAL等類似配置。

app:pointSpacing點與點之間的間距,默認爲最小的點的直徑。

app:pointRadius點的半徑。默認爲3dp。

app:selectedPointRadius選中時點的半徑,默認與pointRadius屬性的值一直,如果你爲pointRadius屬性賦值5dp,那麼該值的默認值就是5dp。

app:pointColor點的顏色。默認爲25%透明度的白色。

app:selectedPointColor選中時點的顏色,默認爲白色。

NumberIndicatorView的自定義屬性

app:totalCount一共有多少個點(也就是總頁數),如果是配合BannerView使用的則以BannerView的頁數爲準。這個屬性最大的用途就是在寫佈局文件時可以及時看到效果,方便調試UI。

android:gravity設置偏移。只支持以下值的單一配置及合理組合:

android:textSize字體大小。

android:textColor字體顏色。

app:separator分隔符號。例如:/

app:separatorTextColor分割符文本顏色。

app:currentPageTextColor當前頁碼文本顏色。

app:totalPageTextColor總頁碼文本顏色。

代碼中使用

//找到控件。
BannerView bannerView = itemView.findViewById(R.id.vp_view_pager);
//設置數據源,默認會啓動輪播。如果不想啓動輪播-bannerView.setEntries(entries, false);
bannerView.setEntries(entries);

設置數據源非常簡單,調用BannerView的public void setEntries(List<? extends BannerEntry> items),setEntries方法有一個重載public void setEntries(@NonNull List<? extends BannerEntry> items, boolean start)第二個參數是說你設置完數據源是否需要啓動輪播。而一個參數的方法模式也是調用的兩個參數的,是默認啓動輪播的。如果你不希望輪播則調用兩個參數的方法。可以看到數據源必須是BannerEntry的子類。

數據模型BannerEntry源碼

public interface BannerEntry<VALUE> {

    /**
     * 創建視圖View。
     */
    View onCreateView(ViewGroup parent);

    /**
     * 獲取標題。
     */
    CharSequence getTitle();

    /**
     * 獲取子標題。
     */
    CharSequence getSubTitle();

    /**
     * 獲取當前頁面的數據。改方法爲輔助方法,是爲了方便使用者調用而提供的,Api本身並沒有任何調用。如果你不需要該方法可以空實現。
     */
    VALUE getValue();

    /**
     * 比較兩個模型是否相同。這個方法類似於Object.equals(Object)方法。
     */
    boolean same(BannerEntry newEntry);
}

大致就這幾個方法,獲取標題、獲取子標題、創建頁面中的View視圖。爲什麼沒有獲取圖片的方法?因爲視圖完全是自己創建的,所以我不需要關心你的圖片是什麼,因爲你有可能是使用本地圖片,也有可能使用網絡圖片。如果是網絡圖片的話,那麼你的圖片加載器有可能是任何方式。所以視圖完全由自己創建。
重要介紹onCreateView方法
這個方法是需要你創建視圖的時候調用的,你需要將你創建好的視圖返回,這有點像Fragment的onCreateView方法,不過你不用擔心,雖然輪播圖是無限輪播的,但是onCreateView並不是每次新的頁面顯示出來就會執行,而是你的輪播圖有幾頁就只會執行幾次,也就是說相對於當前對象而言,只會執行一次。當已經出現過的頁面再次進入屏幕時不會重新執行onCreateView,而是直接複用上一次已經創建好的View。
重要介紹same方法
這個方法是在2.0版本纔有的,這個是幹嘛用的呢?雖然註釋已經寫的很詳細了,我還是要在囉嗦一下。因爲我們設置數據源基本都是在onBindViewHolder的時候設置的,而onBindViewHolder不是隻調用一次,隨着你的ViewHolder在屏幕中的顯示與消失會不停的調用,如果每次設置數據源都刷新視圖的話,將會有點浪費性能,所以我在設置數據源後對數據源進行比較,如果本次設置的數據源與上一次的一致就不進行刷新視圖的操作。但是有些東西並不是我所知道的,比如圖片,我不知道你是本地圖片還是網絡圖片,所以能提供了這樣一個方法。也是爲了提高性能而提供的。

BannerEntry的兩種實現方式

第一種是像下面這種,我稱之爲包裝實現方式,是講我們自己的數據模型包裝到BannerEntry的子類中

private class MyBannerEntry implements SimpleBannerEntry<MyBannerPage> {

    public MyBannerEntry(MyBannerPage bannerPage) {
        super(bannerPage);
    }

    @Override
    public View onCreateView(ViewGroup parent) {
        View entryView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_title_banner_item, parent, false);
        ImageView imageView = entryView.findViewById(R.id.iv_image);
        //這個庫沒有集成圖片框架是因爲大家的項目中所使用的圖片框架可能不是都是一樣的。使用什麼圖片框架應該由大家自己決定,而不是依賴庫來決定。
        Glide.with(parent.getContext())
                .load(getImgUrl())
                .into(imageView);
        return entryView;
    }

    private String getImgUrl() {
        return getValue().getImgUrl();
    }

    @Override
    public CharSequence getTitle() {
        return getValue().getTitle();
    }

    @Override
    public CharSequence getSubTitle() {
        //沒有子標題所以這裏返回null。
        return null;
    }

    @Override
    public boolean same(BannerEntry newEntry) {
        return newEntry != null //兌現不爲null
                && newEntry instanceof MyBannerEntry //類型相同
                && TextUtils.equals(newEntry.getTitle(), getTitle()) //標題相同
                && TextUtils.equals(((MyBannerEntry) newEntry).getImgUrl(), getImgUrl()); //圖片地址相同
    }
}

這種方式適合網絡模型中的字段比較多,而且大多都是有用的。比如我們點擊輪播圖後要將模型攜帶到新的Activity。

第二種是下面這種懶漢實現方式,就是讓我們自己的模型直接實現BannerEntry接口

public class MyBannerEntry implements BannerEntry<String> {
    private final String webUrl;
    private String title;
    private String subTitle;
    private String imgUrl;

    MyBannerEntry(String title, String subTitle, String imgUrl, String webUrl) {
        this.title = title;
        this.subTitle = subTitle;
        this.imgUrl = imgUrl;
        this.webUrl = webUrl;
    }

    @Override
    public View onCreateView(ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_title_banner_item, parent, false);
        ImageView imageView = (ImageView) view.findViewById(R.id.iv_image);
        Glide.with(parent.getContext())
                .load(imgUrl)
                .into(imageView);
        return view;
    }

    /**
     * 獲取標題
     *
     * @return 返回當前條目的標題。
     */
    @Override
    public CharSequence getTitle() {
        return title;
    }

    /**
     * 獲取子標題。
     *
     * @return 返回當前條目的子標題。
     */
    @Nullable
    @Override
    public CharSequence getSubTitle() {
        return subTitle;
    }

    /**
     * 獲取當前頁面的數據。
     *
     * @return 返回當前頁面的數據。
     */
    @Override
    public String getValue() {
        return webUrl;
    }

    @Override
    public boolean same(BannerEntry newEntry) {
        return newEntry instanceof MyBannerEntry 
                && TextUtils.equals(title, newEntry.getTitle()) 
                && TextUtils.equals(subTitle, newEntry.getSubTitle()) 
                && TextUtils.equals(imgUrl, ((MyBannerEntry) newEntry).imgUrl)
                && TextUtils.equals(webUrl, ((MyBannerEntry) newEntry).webUrl);
    }
}

這種方式爲什麼我說是懶漢式呢?因爲我是直接用網絡數據模型實現BannerEntry接口,這麼做就不用在做模型轉換,從網絡框架中得到的數據就直接可以使用。比較適合喜歡偷懶且數據模型中沒有太多字段,或大多字段都沒有什麼用處。

設置監聽

頁面點擊監聽

bannerView.setOnPageClickListener(new BannerView.OnPageClickListener() {
    @Override
    protected void onPageClick(BannerEntry entry, int index) {
        //某個頁面被單擊後執行,entry就是這個頁面的數據模型。index是頁面索引,從0開始。
    }
});

頁面長按監聽

bannerView.setOnPageLongClickListener(new BannerView.OnPageLongClickListener() {
    @Override
    public void onPageLongClick(BannerEntry entry, int index) {
        //某個頁面被長按後執行,entry就是這個頁面的數據模型。index是頁面索引,從0開始。
    }
});

頁面改變監聽

bannerView.setOnPageChangedListener(new BannerView.OnPageChangeListener() {
    @Override
    public void onPageSelected(BannerEntry entry, int index) {
        //某個頁面被選中後執行,entry就是這個頁面的數據模型。index是頁面索引,從0開始。
    }

    @Override
    public void onPageScrolled(int index, float positionOffset, int positionOffsetPixels) {
        //頁面滑動中執行,這個與ViewPage的回調一致。
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        //頁面滑動的狀態被改變時執行,也是與ViewPager的回調一致。
    }
});

到這裏貌似都說完了,可能我說的有點囉嗦了有人更喜歡通過看代碼瞭解,下面我吧完整的代碼發出來吧,便於閱讀我都寫成了內部類。

Demo中所有的代碼

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RecyclerView recyclerView = findViewById(R.id.rv_list);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(getData());
        recyclerView.setAdapter(adapter);
    }

    @SuppressWarnings("unchecked")
    public List getData() {
        List list = new ArrayList();
        list.add(getBannerPagers());
        for (int i = 0; i < 100; i++) {
            list.add("我是條目" + i);
        }
        return list;
    }

    public List<MyBannerPage> getBannerPagers() {
        List<MyBannerPage> list = new ArrayList<>();
        //下面的BannerPage就好比是你從網絡上獲取到的數據模型,大家能明白這個意思就行。
        MyBannerPage bannerPage1 = new MyBannerPage("大話西遊:“炸毛韜”引誘老妖", "http://m.qiyipic.com/common/lego/20171026/dd116655c96d4a249253167727ed37c8.jpg");
        MyBannerPage bannerPage2 = new MyBannerPage("天使之路:藏風大片遇高反危機", "http://m.qiyipic.com/common/lego/20171029/c9c3800f35f84f1398b89740f80d8aa6.jpg");
        MyBannerPage bannerPage3 = new MyBannerPage("星空海2:陸漓設局害慘吳居藍", "http://m.qiyipic.com/common/lego/20171023/bd84e15d8dd44d7c9674218de30ac75c.jpg");
        MyBannerPage bannerPage4 = new MyBannerPage("中國職業脫口秀大賽:狂笑首播", "http://m.qiyipic.com/common/lego/20171028/f1b872de43e649ddbf624b1451ebf95e.jpg");
        MyBannerPage bannerPage5 = new MyBannerPage("奇秀好音樂,你身邊的音樂真人秀", "http://pic2.qiyipic.com/common/20171027/cdc6210c26e24f08940d36a5eb918c34.jpg");

        //將我們所有的BannerPage的實現類都放入的List集合中。
        list.add(bannerPage1);
        list.add(bannerPage2);
        list.add(bannerPage3);
        list.add(bannerPage4);
        list.add(bannerPage5);
        return list;
    }

    private class MyRecyclerViewAdapter extends RecyclerView.Adapter {

        private List items;

        MyRecyclerViewAdapter(List items) {
            this.items = items;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == 0) {
                return new BannerViewHolder(parent);
            } else {
                return new ItemViewHolder(parent);
            }
        }

        @Override
        public int getItemViewType(int position) {
            return position == 0 ? 0 : 1;
        }

        @Override
        @SuppressWarnings("unchecked")
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (getItemViewType(position) == 0) {
                BannerViewHolder viewHolder = (BannerViewHolder) holder;
                List<MyBannerPage> o = (List<MyBannerPage>) items.get(position);
                ArrayList<MyBannerEntry> entries = new ArrayList<>();
                for (MyBannerPage page : o) {
                    entries.add(new MyBannerEntry(page));
                }
                viewHolder.mBannerView.setEntries(entries);
            } else {
                ItemViewHolder viewHolder = (ItemViewHolder) holder;
                viewHolder.mTextView.setText((String) items.get(position));
            }
        }

        @Override
        public int getItemCount() {
            return items == null ? 0 : items.size();
        }
    }

    private class BannerViewHolder extends RecyclerView.ViewHolder {
        private final BannerView mBannerView;

        BannerViewHolder(ViewGroup parent) {
            super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_banner_layout, parent, false));
            mBannerView = itemView.findViewById(R.id.vp_view_pager);
            mBannerView.setOnPageClickListener(new BannerView.OnPageClickListener() {
                @Override
                protected void onPageClick(BannerEntry entry, int index) {
                    //因爲index是索引而索引是從0開始的所以表示頁數是:index+1
                    Toast.makeText(getApplicationContext(), String.format(Locale.CHINA, "您點擊了BannerView的第%d頁!", index + 1), Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

    private class ItemViewHolder extends RecyclerView.ViewHolder {
        private final TextView mTextView;

        ItemViewHolder(ViewGroup parent) {
            super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_normal_layout, parent, false));
            mTextView = (TextView) itemView;
        }
    }

    private class MyBannerEntry implements BannerEntry<MyBannerPage> {

        private MyBannerPage mBannerPage;

        public MyBannerEntry(MyBannerPage bannerPage) {
            mBannerPage = bannerPage;
        }

        @Override
        public View onCreateView(ViewGroup parent) {
            View entryView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_title_banner_item, parent, false);
            ImageView imageView = entryView.findViewById(R.id.iv_image);
            //這個庫沒有集成圖片框架是因爲大家的項目中所使用的圖片框架可能不是都是一樣的。使用什麼圖片框架應該由大家自己決定,而不是依賴庫來決定。
            Glide.with(parent.getContext())
                    .load(getImgUrl())
                    .into(imageView);
            return entryView;
        }

        private String getImgUrl() {
            return mBannerPage.getImgUrl();
        }

        @Override
        public CharSequence getTitle() {
            return mBannerPage.getTitle();
        }

        @Override
        public CharSequence getSubTitle() {
            //沒有子標題所以這裏返回null。
            return null;
        }

        @Override
        public MyBannerPage getValue() {
            //這個方法api本身沒有任何調用,也可以空實現。是爲方便開發者而提供的。有點類似於View.getTag()方法。
            return mBannerPage;
        }

        @Override
        public boolean same(BannerEntry newEntry) {
            return newEntry != null //兌現不爲null
                    && newEntry instanceof MyBannerEntry //類型相同
                    && TextUtils.equals(newEntry.getTitle(), getTitle()) //標題相同
                    && TextUtils.equals(((MyBannerEntry) newEntry).getImgUrl(), getImgUrl()); //圖片地址相同
        }
    }

    private class MyBannerPage {
        private String title;
        private String imgUrl;

        public MyBannerPage(String title, String imgUrl) {
            this.title = title;
            this.imgUrl = imgUrl;
        }

        public String getTitle() {
            return title;
        }

        public String getImgUrl() {
            return imgUrl;
        }
    }
}

Demo中所有的佈局文件

R.layout.activity_main

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rv_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

R.layout.item_banner_layout

<?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"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="175dp"
                android:orientation="vertical">

    <com.kelin.banner.view.BannerView
        android:id="@+id/vp_view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:bannerIndicator="@+id/biv_indicator"
        app:titleView="@+id/tv_title"
        app:pagingIntervalTime="3000"
        app:singlePageMode="canNotPaging|noIndicator"
        app:decelerateMultiple="4"
        android:background="#FFF"/>

    <LinearLayout android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_alignParentBottom="true"
                  android:background="#8000"
                  android:gravity="center_vertical"
                  android:orientation="horizontal"
                  android:padding="6dp">

        <!--用來顯示標題的控件-->
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:textColor="@android:color/white"
            android:textSize="15sp"
            android:textStyle="bold"
            tools:text="我是標題!"/>

        <!--Banner的圓點型指示器-->
        <com.kelin.banner.view.PointIndicatorView
            android:id="@+id/biv_indicator"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:totalCount="4"
            app:pointRadius="3dp"
            app:selectedPointRadius="4dp"
            app:pointSpacing="4dp"
            app:pointColor="#5fff"
            app:selectedPointColor="@android:color/white"/>
    </LinearLayout>
</RelativeLayout>

R.layout.item_normal_layout

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:paddingBottom="16dp"
          android:paddingLeft="8dp"
          android:paddingRight="8dp"
          android:paddingTop="18dp"
          android:textColor="@android:color/black"
          android:textSize="16sp"
          tools:text="條目一"/>

R.layout.layout_title_banner_item

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
           xmlns:tools="http://schemas.android.com/tools"
           android:id="@+id/iv_image"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:scaleType="centerCrop"/>

創作不易希望給個Star,你的支持是我的動力!如果有意見或者建議可以在下方留言也可以在GitHub上留言或者發郵件給我。

歡迎光臨我的GitHub項目地址點擊傳送

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章