Android客戶端實現圖片輪播控制元件

NO IMAGE

本文和大家一起寫一個Android圖片輪播控制元件,供大家參考,具體內容如下

1. 輪播控制元件的組成部分

    我們以知乎日報Android客戶端的輪播控制元件為例,分析一下輪播控制元件的主要組成:   

    首先我們要有用來顯示圖片的View物件,根據上圖中底部中央的5個點,我們知道需要5個ImageView來顯示需要輪播的圖片,另外還需要5個ImageView來顯示5個點。現在考慮以下輪播元件應該具有的行為,首先需要每隔一定時間間隔切換到下一張圖片,並且圖片間切換的效果應該是平滑的,就像“翻書”一樣。由此我們可以想到將5個圖片當做ViewPager的Page,這樣圖片切換時自然會有平滑的效果。接下來,我們還要給底部的5個小點找一個父容器,由於它們是線性排列的,所以用LinearLayout是再合適不過了。然後,我們還要把ViewPager和容納5個點的LinearLayout放入一個父容器中,這裡我們選擇使用垂直排列子View的LinearLayout。

    這樣一來,我們就得到了輪播控制元件的佈局檔案(carousel_layout.xml):


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@ id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@ id/dots"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:gravity="center"
android:orientation="horizontal"
android:padding="8dp" >
</LinearLayout>
</LinearLayout>

    通過對輪播控制元件的組成部分進行分析,我們已經確定了用什麼“資料結構”來表示一個輪播元件,那麼接下來,我們要做的就是實現輪播元件的”演算法“,也就是業務邏輯。

2. 輪播元件的行為分析

    輪播控制元件首先要具有的行為是自動播放,也就是每隔一定事件間隔(通常是3到5秒),便自動”翻到下一頁“。為了實現這一點,我們可以維護一個currentItem變數來記錄當前正在顯示的圖片,然後設定一個定時任務,呼叫ViewPager的setCurrentItem方法設定當前要顯示的圖片,並將currentItem設為下一張要顯示的圖片。有一點需要我們注意的便是播放到最後一張圖片時,下一個被顯示的應該是第一個圖片,而且切換的效果也不再是平滑的。

    輪播控制元件的還要能響應我們的滑動動作,也就是我們能夠通過左右滑動來在不同的圖片之間切換,這個行為ViewPager自動為我們提供了。另外還有一個輪播控制元件應該具備的行為是:當切換到指定圖片時,相應的圓點應該以區別其他4個圓點的顏色顯示,以便使用者能夠知道當前正在播放的是第幾個圖片。要實現這一點也不復雜,只需要為ViewPager新增一個OnPageChangeListener監聽器,然後重寫相應的回撥方法即可,這樣當使用者選定了某個Page時,onPageSelected方法會被回撥,系統會傳入當前Page的索引,我們便可以根據這個索引設定相應的圓點顏色。

 3. 輪播控制元件的具體實現

    經過以上的分析,我們已經清楚的瞭解了輪播元件的表示及業務邏輯,接下來只要我們用Java把這些描述出來就大功告成了。

(1)定時任務
    我們需要定時執行“改變ViewPager當前Page為下一個Page”這一任務,這裡我們採用Handler來實現,程式碼如下:


mHandler.postDelayed(task, DELAY);
private final Runnable task = new Runnable() {
@Override
public void run() {
if (isAutoPlay) {
currentItem = (currentItem   1) % (mTopStories.size());
mVP.setCurrentItem(currentItem);
mHandler.postDelayed(task, DELAY);
} else {
mHandler.postDelayed(task, DELAY);
}
}
};

    在以上程式碼中,DELAY代表我們設定的一個延遲常量(單位ms)。由於我們需要的是迴圈播放,因此第5張顯示完畢後應該顯示第一張,所以我們要想第6行那樣進行一個模運算,這樣currentItem就在0到4之間不停變化了。注意第5行有一個isAutoPlay變數,這個變數表示當前是否應該自動播放。那麼什麼時候不應該自動播放呢?我們知道當我們滑動手指切換圖片時,圖片會“跟隨”著我們的手,就好比我們翻書頁的時候,只有鬆開了手書頁才能落下。所以我們正在“拖動”圖片時,也就是我們的手還沒鬆開時,輪播控制元件是不應該自動播放的。為了實現這一點,我們只需重寫OnPageChangeListener中的onPageScrollStateChanged方法,在當前狀態為“拖動”時設定isAutoPlay變數為false。從第10行我們可以知道,當autoPlay為false時,不會改變當前顯示的圖片,僅僅會等過了DELAY指定的時間後再執行下一次定時任務。 

(2)OnPageChangeListener
    上面我們提到了要給ViewPager新增一個OnPageChangeListener監聽器物件,來實現小圓點顏色的改變以及autoPlay變數的賦值。具體的實現請看以下程式碼,程式碼的含義都很直接:


class TopOnPageChangeListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
for (int i = 0; i < mDotsIV.size(); i  ) {
if (i == position) {
mDotsIV.get(i).setImageResource(R.drawable.dot_focus);
} else {
mDotsIV.get(i).setImageResource(R.drawable.dot_blur);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
switch (state) {
//SCROLL_STATE_DRAGGING
case 1:
isAutoPlay = false;
break;
//SCROLL_STATE_SETTLING
case 2:
isAutoPlay = true;
break;
default:
break;
}
}
}

    在以上程式碼的第10到16行,我們重寫了onPageSelected方法,position參數列示當前Page的索引。這個方法中,我們設定當前圖片對應的圓點圖片為dot_focus,設定其他圓點的圖片為dot_blur,這樣使用者就能知道當前的位置。在第21行到32行,我們重寫了onPageScrollStateChanged方法,state引數代表了當前的“滾動狀態,這個值為1表示當前使用者正在”拖動“的過程中,因此要設定isAutoPlay為false;這個值為2表示使用者鬆開了手,圖片正在”滾動“中,這時我們就要把isAutoPlay設回預設值true,恢復自動播放。

 (3) 更進一步
    有時候我們希望能夠從最後一頁直接“翻到”第一頁,而這種行為預設不被PagerView所支援,要想實現這個行為,我們可以在PagerView中增加一些“輔助頁”,並重寫OnPageChangeLisener中的相關方法。然而我們在很多場景中只需要保持PagerView的預設行為就好,要注意增加任何功能都要考慮應用場景,避免畫蛇添足。