Android-你可能不知道的Drawable用法

denko發表於2019-04-01

今天為了適配啟動頁背景圖,接觸到了BitmapDrawable保證了時的背景圖不變形。想想之前真的沒用過,所以還是有必要詳細瞭解一下Drawable,至少在遇到一些問題時可以及時的找到解決方案。

Drawable的分類

Drawable一般都是用XML定義的,但是我們也可以自定義Drawable,但是程式碼會比較複雜。

BitmapDrawablw

可以理解為它是一張帶規則的圖片,一般情況下如果可以在ImageView裡面設定屬性的就沒必要使用,但是如果一張圖片要做到像放在控制元件裡適配就有必要使用了,例如啟動頁背景圖

<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="clip_horizontal|clip_vertical"
    android:dither="true"
    android:src="@drawable/splash_bg"
    android:tileMode="disabled"/>
    <!--屬性解釋-->
    <!--android:src 圖片資源id-->
    <!--android:antialias是否開啟抗鋸齒,應該開啟-->
    <!--android:dither是否開啟抖動效果,應該開啟-->
    <!--android:filter是否開啟過濾效果,應該開啟-->
    <!--android:gravity對圖片進行定位-->
    <!--android:mipMap紋理對映,一般為false-->
    <!--android:tileMode平鋪模式四個值:disabled(預設值即關閉平鋪模式)、clamp、repeat、mirror-->
複製程式碼

如果直接使用圖片,由於不能控制圖片的位置,有些手機會變形很嚴重。

NinePatchDrawable

與BitmapDrawable類似不過NinePatchDrawable的效果類似於.9圖,實際使用時其實直接使用.9圖就好

ShapeDrawable

開發時用的比較多,可以理解為只有純顏色或漸變色的圖片。只是有些地方需要注意一下。

以上程式碼是一個指定漸變百分比的漸變shape,其中centerY與centerColor必須同時設定才能生效,否則只是普通的漸變,另外,其實我們的系統進度條也可以設定漸變

       <ProgressBar
             style="@style/Widget.AppCompat.ProgressBar.Horizontal"
                android:layout_width="match_parent"
                android:layout_height="3dp"
                android:max="1000"
                android:progress="0"
                android:progressDrawable="@drawable/progress_green" />

複製程式碼
       <ProgressBar
             style="@style/Widget.AppCompat.ProgressBar.Horizontal"
                android:layout_width="match_parent"
                android:layout_height="3dp"
                android:max="1000"
                android:progress="0"
                android:progressDrawable="@drawable/progress_green" />

複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<!--progress_green-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="50dp" />
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <scale
            android:drawable="@drawable/progress_shape"
            android:scaleWidth="100%" />
    </item>
</layer-list>
複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<!--progress_shape-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:angle="0"
        android:endColor="@color/theme_color"
        android:startColor="@color/theme_color1"
        android:type="linear" />
</shape>
複製程式碼

進度條max的值由於沒有小數,所以設定1000效果會好很多,加上動畫效果後效果如下

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <!--<solid android:color="#F4D78C" />-->
    <gradient
        android:angle="90"
        android:centerY="0.7"
        android:endColor="@color/green_00A9BA"
        android:centerColor="@color/theme_color1"
        android:startColor="@color/theme_color1"></gradient>
</shape>
複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<!--progress_green-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="50dp" />
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <scale
            android:drawable="@drawable/progress_shape"
            android:scaleWidth="100%" />
    </item>
</layer-list>
複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<!--progress_shape-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:angle="0"
        android:endColor="@color/theme_color"
        android:startColor="@color/theme_color1"
        android:type="linear" />
</shape>
複製程式碼

進度條max的值由於沒有小數,所以設定1000效果會好很多,加上動畫效果後效果如下

-c

LayerDrawable

對應的標籤是layer-list,表示一種層次化的Drawable。很多時候都可以使用佈局巢狀完成,但是使用layor-list可以減少佈局的層級結構,例如

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <stroke android:width="1dp" android:color="#45DAA8" />
        </shape>
    </item>

    <item>
        <bitmap android:src="@drawable/gou"
            android:gravity="bottom|right" />
    </item>
</layer-list>
複製程式碼

效果圖

Android-你可能不知道的Drawable用法

StateListDrawble

這個開發中也經常用到,標籤對應的是selector。比如我們的點選效果、還有選擇後與選擇前的不同效果,使用selector可以在程式碼中設定一個屬性改變很方便。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="true" android:drawable="@drawable/bg_btn_circle_gradient_full">
    </item>

    <item android:state_enabled="false">

        <ripple xmlns:android="http://schemas.android.com/apk/res/android"
            android:color="#aaffffff">
            <item>
                <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
                    <corners android:radius="360dp" />
                    <solid
                        android:color="@color/gray_eeeeee"
                        />
                </shape>
            </item>
        </ripple>

    </item>
</selector>
複製程式碼

這裡結合了ripple標籤,可以做出水波紋效果。效果如下

Android-你可能不知道的Drawable用法

LevelListDrawable

也是一個Drawable的集合,對應的標籤是level-list。有點類似於layer-list,不過level-list是根據等級(0~10000)來顯示的,而layer-list則是顯示在一起的。開發中比較少用到,如果一個按鈕有多種狀態可以考慮使用代替if-else判斷顯示

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/icon_heat" android:maxLevel="1"/>
    <item android:drawable="@drawable/icon_cool" android:maxLevel="2"/>
</level-list>
複製程式碼
imageview.getDrawable().setLevel(1);
複製程式碼

TransitionDrawable

可以實現兩個Drawable之間的淡入淡出,對應的標籤是transition。

ScaleDrawable

對應的標籤是scale,可以根據level指定Drawable縮放到一定比例。

這兩個效果我覺得可以在啟動頁的背景圖做一點動畫效果或者做全域性的動畫,其他地方可以使用動畫代替。

InsetDrawable

對應的標籤是inset,可以把Drawable內嵌進來,可以用於加大點選區域。

ClipDrawable

對應的標籤是clip,可以根據level裁剪出另外一個drawabl。挺有用的一個Drawable可以看看下面的部落格 效果圖:

-c

blog.csdn.net/briblue/art…

自定義Drawable

其實Drawable是一個抽象的概念,可以理解為Canvas之前的一個封裝。就是把資源封裝成Drawable再繪製到畫布上。Drawable可以說是記憶體級的畫布。

過程與自定義View時的繪畫是相似的,具體也上面ClipDrawable的部落格。

參考資料

《Android開發藝術探索》


Android-你可能不知道的Drawable用法

最開始堅持的地方,記錄學習與生活的點點滴滴

相關文章