定制觸摸反饋:RippleDrawable

為了更好的在5.0及以上設備上使用波紋效果,簡單跟大家聊下RippleDrawable的正確打開方式,如何方便快捷的定義不同的觸摸反饋的范圍以及波紋擴散的顏色,最后聊下5.0以下設備上的兼容方案

為了在5.0以上設備上實現波紋效果,我們可以通過給View設置background實現,而這個效果,官方已經有兩個已經實現的效果供我們選擇: ?android:attr/selectableItemBackground 和 ?android:attr/selectableItemBackgroundBorderless ,這兩條屬性不僅產生的效果不太一樣,使用方式上也有些不同,第一條屬性是可以隨意用的,它是有向下兼容的能力,在5.0以下的設備上沒有波紋效果,是普通的變色效果;而第二條屬性只支持5.0及以上設備,RequiresApi = 21, 所以如果要使用它的話,一定要考慮兼容性問題。它們的效果也是不一樣的:第一個的波紋效果會被限制在View的大小之內,而第二條屬性的波紋擴散范圍是圓形的,而且圓的大小是以View最遠距離點距離View中心點距離為半徑,就是說:波紋的擴散范圍保證會覆蓋整個View,而且會擴散出View。官方提供的解決方法有一點不好就是無法定制,我們不能很方便的自定義波紋效果的顏色以及大小,所以官方還是有另外一個類來讓我們折騰,那就是:RippleDrawable,接下來我們將用自己的代碼來一一實現我們上面剛剛討論過的兩種效果。

RippleDrawable

RippleDrawable 繼承自 LayerDrawable , 可以實現多個Layer的層疊,今天只討論用xml的形式來配置 Ripple ,就是普通的在drawable文件夾下新建一個drawable,它的最外層標簽是 ripple :

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorAccent"
        >

</ripple>

上面這段簡單的代碼就幫我們實現了一個 color 自定義的 ?android:attr/selectableItemBackgroundBorderless 的效果,直接給目標view設置background屬性,就能看到熟悉的波紋效果,如下圖返回鍵的波紋效果:

我們繼續在它上面修改來實現第一條屬性的效果:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorAccent"
        >
    <item
            android:id="@android:id/mask"
            android:drawable=""@android:color/white"/>

</ripple>

只是在原來的代碼中加上了一個 item 標簽,還給這個標簽設置了一個 id="@android:id/mask" ,后面的那個 drawable 屬性設置了波紋效果的擴散范圍,這時候再運行我們的程序,發現波紋擴散的范圍果然被限制住了,如下圖中返回按鈕的效果所示:

但是,等等,設置background之后,我的View背景豈不是一篇空白?放心,我們繼續改代碼:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorAccent"
        >
    <item
            android:id="@android:id/mask"
            android:drawable="@android:color/white"/>

    <item android:drawable="@color/colorPrimary"/>

</ripple>

修改之后再次執行我們的程序,運行效果如下圖中Simple Button的點擊效果所示:

總算大功告成!既有了我們定義的背景,還實現了點擊時的波紋效果,唯一的不足可能就是不支持5.0以下的設備,這點因為系統的限制我們就不做考慮了,我們會在后面討論怎么保證5.0以下設備不會崩潰。

我們來分析一下最后這段代碼:定義在 ripple 節點的顏色定義的是最后我們想要的波紋的顏色,里面的兩個 item 標簽分別定義了波紋擴散的范圍以及普通狀態目標View的顏色,它是怎么區分兩個 item 的呢?沒錯,就是通過 id ,因為在第一個 item 設置了 android:id="@android:id/mask" ,所以這個 item 不會出現被繪制在屏幕上,只會已蒙層的形式定義波紋的范圍,如果沒有這個定義這個id的item,那么 ripple 會根據綜合所有的item最后得到波紋擴散的范圍,再極端,如果一個 item 都沒有呢?那就看到我們前面說到的第二種情況:波紋會擴散到parentView的范圍內。

如果 ripple 中有多個普通的 item 標簽,效果會和 layer-list 效果類似,多個item的drawable會疊加在一起,定義了 mask id的 item 和普通 item 之間不會有影響。

因為在測試的時候一直用的 Button 測試,偶然的機會在 ImageView 上使用,發現竟然不生效,搜索了一下才發現只有當View的clickable屬性為true的時候,波紋效果才會生效。

5.0以下的兼容方案

既然5.0以上的設備可以實現效果了,5.0以下的設備也不能讓它直接崩潰,下面有兩種兼容方案:

  1. layout-v21方案,相信大家都比較熟悉,寫兩份 ripple_drawable 文件,分別在layout-v21文件夾下和普通layout文件夾下,普通layout文件夾的 ripple_drawable 為空或者設置普通的點擊效果,只要不使用 ripple 標簽就好。

  2. 代碼設置,相對省代碼,但是比較費腦,不太跳進,具體大家可以看代碼:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        int[] attrs = new int[] { android.R.attr.selectableItemBackgroundBorderless};
        TypedArray ta = obtainStyledAttributes(attrs);
        button1.setBackground(ta.getDrawable(0));
        ta.recycle();
    } else {
        // do something on devices below 21
    }
    

 

來自:http://shaohui.xyz/2017/03/08/ripple_drawable/

 

 本文由用戶 bpkx3107 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!