ViewPager經過PageTransformer實現切換時背景色的漸變

定個小目標

咱們要實現以下的效果,ViewPager正中的page顯示爲綠色,其他兩邊的顯示爲藍色。中間page像左右兩邊切換時會從綠色慢慢過渡到藍色,同理兩邊的page向中間切換時顏色也會慢慢過渡,而不是直接跳變。 bash

PageTransformer

爲了實現以上效果咱們要藉助PagerTransfromer,因此有必要簡單介紹下微信

/**
 * A PageTransformer is invoked whenever a visible/attached page is scrolled.
 * This offers an opportunity for the application to apply a custom transformation
 * to the page views using animation properties.
 *
 * <p>As property animation is only supported as of Android 3.0 and forward,
 * setting a PageTransformer on a ViewPager on earlier platform versions will
 * be ignored.</p>
 */
public interface PageTransformer {
    /**
     * Apply a property transformation to the given page.
     *
     * @param page Apply the transformation to this page
     * @param position Position of page relative to the current front-and-center
     *                 position of the pager. 0 is front and center. 1 is one full
     *                 page position to the right, and -1 is one page position to the left.
     */
    void transformPage(View page, float position);
}
複製代碼

PageTransformer很簡單,就只有一個transformPage方法。
第一個參數是咱們要變換顏色的page。app

重點看第二個參數,英語好的話直接看註釋說得很明白,意思就是咱們當前要變化的頁面當前位置的中心距離pager中心的距離,好比當前處於中心的page的position就是0,右邊第一個page的position=1,右邊第二個page的position爲2,左邊第一個page的position=-1,左邊第二個page的position=-2,以此類推。ide

固然position的值不可能一直是整數,好比當處於中間位置的page向右邊切換到右邊第一個位置時,position的值會從0變化到1,1就是表示一個page的寬度,從中間位置移到右邊第一個位置就是移動了一個page的寬度。若是向右移動到一半,那麼position就是0.5。 ui

實現的思路

只有中間位置是綠色,其他兩邊的都是藍色,因此能夠肯定的是position=0,確定是綠色,position的絕對值Math.abs(position)>=1必定是藍色,剩下的咱們就是要處理-1<position<1這些位置的漸變色,也就是中間位置到左右兩邊第一個page的位置。this

中間位置到左右兩邊第一個page的位置的position取絕對值的值範圍從0-1,其實就是0%-100%,咱們能夠用這個值當作顏色的變化率,0就是綠色,值越大表示越往藍色變化,1就表示變成藍色了。spa

另外一個難點就是如何實現顏色的漸變。咱們知道顏色由RGB表示,有三個顏色的份量分別表示紅綠藍。咱們把起始顏色和最終顏色的三個顏色份量分別取出來,分別計算三個顏色份量的差值,最後用差值乘以變化率再加上初始顏色份量就是當前的顏色份量值,把三個當前顏色份量的值拼起來就是當前的顏色值。3d

初始顏色:#00ff00
最終顏色:#0000ff
初始顏色份量:紅00,綠ff(255),藍00
最終顏色份量:紅00,綠00,藍ff(255)
顏色份量差值:紅00,綠-255,藍255code

假設咱們要計算position=0.5位置的顏色 當前紅色份量=0+0.500=0=0x00
當前綠色份量=255+0.5
(-255)=127=0x7f
當前藍色份量=0+0.5*255=127=0x7form

因此position=0.5時當前的顏色爲#007f7f。

代碼實現

一個很簡單的功能說了這麼多,就是爲了讓你們更好的理解,若是直接放代碼看了坑能會一頭霧水

設置PagerTransfromer

mViewPager.setPageTransformer(true, new ViewPager.PageTransformer() {
    @Override
    public void transformPage(@NonNull View view, float v) {
        // 取絕對值
        v = Math.abs(v);
        // 超過左右兩邊第一個位置的page都設置成藍色
        if (v > 1) {
            v = 1;
        }
        String color = transColor("#00ff00", "#0000ff", v);
        view.setBackgroundColor(Color.parseColor(color));
    }
});
複製代碼

計算當前顏色值

/**
 * 根據起始顏色、最終顏色和變化率計算當前顏色
 * @param start 起始顏色
 * @param end 最終顏色
 * @param rate 變化率
 * @return 當前顏色
 */
private static String transColor(String start, String end, float rate) {
    // 獲取初始顏色的RGB份量
    String startR = start.substring(1, 3);
    String startG = start.substring(3, 5);
    String startB = start.substring(5, 7);
    // 獲取最終顏色的顏色份量
    String endR = end.substring(1, 3);
    String endG = end.substring(3, 5);
    String endB = end.substring(5, 7);
    // 計算初始顏色的RGB份量十進制值
    int startRI = Integer.parseInt(startR, 16);
    int startGI = Integer.parseInt(startG, 16);
    int startBI = Integer.parseInt(startB, 16);
    // 計算最終顏色的RGB份量十進制值
    int endRI = Integer.parseInt(endR, 16);
    int endGI = Integer.parseInt(endG, 16);
    int endBI = Integer.parseInt(endB, 16);
    // 計算當前顏色份量
    int curRI = (int) (startRI + (endRI - startRI)*rate);
    int curGI = (int) (startGI + (endGI - startGI)*rate);
    int curBI = (int) (startBI + (endBI - startBI)*rate);
    // 轉成16進制
    String curR = String.format("%02x", curRI);
    String curG = String.format("%02x", curGI);
    String curB = String.format("%02x", curBI);
    // 拼成顏色碼
    return "#" + curR + curG + curB;
}
複製代碼

若是喜歡個人文章,能夠掃描如下二維碼關注個人微信公衆號,我會按期發佈最新的文章。
關注個人微信,回覆背景色漸變獲取本文的完整代碼。

相關文章
相關標籤/搜索