Drawable資源是Android應用中使用最普遍的資源,它不只可使用各類格式的圖片資源,也可使用多種xml文件資源。
1.一種能夠在Canvas上進行繪製的抽象的概念; 2.顏色、圖片等均可以是一個Drawable; 3.Drawable能夠經過XML定義,或者經過代碼建立; 4.Android中Drawable是一個抽象類,每一個具體的Drawable都是其子類;html
Drawable的子類包括ColorDrawable、GradientDrawable、BitmapDrawable、NinePatchDrawable、InsetDrawable、ClipDrawable、ScaleDrawable、RotateDrawable、AnimationDrawable、LayerDrawable、StateListDrawable、TransitionDrawable、VectorDrawable、ShapeDrawablejava
A specialized Drawable that fills the Canvas with a specified color.android
ColorDrawable是最簡單的Drawable,也是平時用的最多的,好比:canvas
android:background = "@color/colorAccent"app
ColorDrawable是一個專門用來使用指定的顏色來填充畫布的Drawable,當它被繪製到畫布上時會使用一種指定的顏色填充Paint,在畫布上繪製出一塊單色區域。ide
在xml文件中使用color做爲根節點來建立ColorDrawable,它只有一個android:color屬性,經過它來決定ColorDrawable的顏色,這個顏色一旦設置以後,就不能直接修改了。post
<?xml version="1.0" encoding="utf-8"?> <color xmlns:android="http://schemas.android.com/apk/res/android" android:color="#ff000000" />
經過java代碼也能夠建立ColorDrawable,代碼以下:動畫
ColorDrawable drawable = new ColorDrawable(0xff000000);this
A Drawable that wraps a bitmap and can be tiled, stretched, or aligned.spa
BitmapDrawable是對bitmap的一種包裝,能夠設置它包裝的bitmap在BitmapDrawable區域內的繪製方式,如平鋪、拉伸填充或者保持圖片原始尺寸,也能夠在BitmapDrawable區域內部使用gravity指定的對齊方式。
在xml文件中使用bitmap做爲根節點來定義BitmapDrawable。
<?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/arrow_down" android:tileMode="mirror" android:antialias="true" android:dither="true" />
其中,src爲引用的圖片資源;tileMode屬性表示平鋪模式,一共有4中屬性:mirror,repeat,clamp,disabled;dither屬性表示是否開啓抖動,通常爲true;antialias屬性表示是否開啓抗鋸齒功能,通常爲true; 也可使用java代碼實現上述相同的效果,等價的java代碼以下:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.arrow_down); BitmapDrawable mBitmapDrawable = new BitmapDrawable(bitmap); mBitmapDrawable.setTileModeXY(TileMode.MIRROR,TileMode.MIRROR); mBitmapDrawable.setAntiAlias(true); mBitmapDrawable.setDither(true); mDrawable = mBitmapDrawable;
A Drawable with a color gradient for buttons, backgrounds, etc.
GradientDrawable表示一個漸變區域,能夠實現線性漸變、發散漸變和平鋪漸變效果; 在xml文件中使用shape做爲根節點來建立GradientDrawable,它包含不少屬性和子節點,具體以下:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle | oval | ring | line"> // 矩形 //內部填充色 <solid android:color="@color/red" /> //圓角半徑 <corners android:radius="5dp" /> //邊框顏色和寬度 <stroke android:color="@color/orange" android:width="5dp" /> //漸變色 <gradient android:angle="integer" //漸變角度(默認爲0,即從左到右),須爲45的倍數,爲0時從左到右 //爲90時從上到下,該屬性僅對線性漸變有效 android:centerX="integer" //漸變中心X的相對位置,範圍從0~1 android:centerY="integer" //漸變中心Y的相對位置,範圍從0~1 android:startColor="color" //顏色漸變的開始顏色 android:centerColor="integer" //顏色漸變的中心顏色 android:endColor="color" //顏色漸變的結束顏色 android:gradientRadius="integer" //漸變半徑,只有當type爲radial時才能使用 android:type=["linear" | "radial" | "sweep"] //默認值爲linear,即線性漸變,radial(放射性漸變),sweep(掃描式漸變) android:useLevel=["true" | "false"] //設置爲false纔有漸變效果 /> //指定大小 <size android:width="45dp" android:height="45dp" /> //內邊距 <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" />
在代碼中動態建立GradientDrawable樣例以下:
private Gradient getDrawable(int radius,int fillColor,iunt width,int strokeColor) { GradientDrawable gradientDrawable = new GradientDrawable(); gradientDrawable.setCornerRadius(radius); gradientDrawable.setColor(fillColor); gradientDrawable.setStroke(width,strokeColor); return gradientDrawable; }
可實現drawable中shape樣式的功能,setColor()至關於shape中的填充色,setCornerRadius()用來設置shape的圓角半徑,setStroke(int width,int color)用來設置邊框的寬度和顏色。
ScaleDrawable是對一個Drawable進行縮放操做,能夠根據level屬性控制這個drawable的縮放比例,也能夠設置它在容器中的對齊方式。在xml文件中使用scale做爲根節點來建立ScaleDrawable,建立ScaleDrawable的代碼以下:
<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/drawable_resource" android:scaleGravity=["top" | "bottom" | "left" | "right" | "center_vertical" | "fill_vertical" | "center_horizontal" | "fill_horizontal" | "center" | "fill" | "clip_vertical" | "clip_horizontal"] android:scaleHeight="percentage" android:scaleWidth="percentage" />
定義一個scale.xml:
<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/image" android:scaleGravity="center_vertical|center_horizontal" android:scaleHeight="50%" android:scaleWidth="50%" />
而後在layout中使用:
<ImageView android:id="@+id/imgView" android:src="@drawable/scale" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
可是若是直接運行,圖片並無顯示,緣由是draw()方法中只有當getLevel()!=0時才繪製;而咱們在沒有se't'Level()時,默認getLevel()爲0;
比例縮放的計算公式以下:
w -= (int) (w * (10000 - level) * mState.mScaleWidth / 10000); h -= (int) (h * (10000 - level) * mState.mScaleHeight / 10000);
當level設置爲10000時,顯示爲圖片原始大小;當level爲0時,圖片不顯示;所以通常將level設置爲1,這樣圖片就會根據android:scaleHeight和android:scaleWidth進行相應的縮放。
RotateDrawable用來控制drawable的旋轉,在xml文件中使用rotate做爲根元素來建立RotateDrawable:
rotate.xml <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:pivotX="50%" android:pivotY="50%" android:visible="true" android:fromDegrees="0" android:toDegrees="360" android:drawable="@mipmap/cd" > </rotate>
使用時經過ImageView的src屬性對該RotateDrawable進行引用
<ImageView android:id = "@+id/iv" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:src = "@drawable/rotate" />
在activity中經過iv.getDrawable().setLevel(int level)對RotateDrawable進行控制(level的值在0~10000之間)
AnimationDrawable是用來實現Android幀動畫的,就是把一系列的Drawable按照必定的順序一幀幀的播放;只適用於不要進行控制的幀動畫,例如刷新時的進度條素材。 在xml文件中使用<animation-list>做爲根節點來建立AnimationDrawable;相關的屬性方法以下:
再得到AnimationDrawable實例後,須要調用它的start方法來播放動畫,另外要注意在onCreate()方法中調用的話,是沒有任何效果的,由於View還沒完成初始化;咱們能夠用簡單的handler來延遲播放動畫;其餘的實現方法可參考如下連接:Android AnimationDrawable運行的幾種方式 ;
實際使用實例:
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@mipmap/ic_pull_to_refresh_loading01" android:duration="100" /> <item android:drawable="@mipmap/ic_pull_to_refresh_loading02" android:duration="100" /> <item android:drawable="@mipmap/ic_pull_to_refresh_loading03" android:duration="100" /> <item android:drawable="@mipmap/ic_pull_to_refresh_loading04" android:duration="100" /> <item android:drawable="@mipmap/ic_pull_to_refresh_loading05" android:duration="100" /> <item android:drawable="@mipmap/ic_pull_to_refresh_loading06" android:duration="100" /> </animation-list>
public class MainActivity extends AppCompatActivity { private ImageView img_show; private AnimationDrawable ad; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); img_show = (ImageView) findViewById(R.id.img_show); //核心代碼 ad = (AnimationDrawable)img_show.getDrawable(); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { ad.start(); } },300); } }
LayerDrawable對應的xml標籤是<layer-list>,它表示一種層次化的Drawable集合,經過將不一樣的Drawable放置在不一樣的層上從而達到一種疊加後的效果。 在xml文件中建立LayerDrawable的代碼以下:
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <bitmap android:src="@drawable/type_newgmae_icon" android:gravity="center" /> </item> <item android:top="15dp" android:left="15dp"> <bitmap android:src="@drawable/type_networkgame_icon" android:gravity="center"/> </item> <item android:top="30dp" android:left="30dp"> <bitmap android:src="@drawable/type_necessary_icon" android:gravity="center" /> </item> </layer-list>
實現的效果以下:
A Drawable that clips another Drawable based on this Drawable's current level value. You can control how much the child Drawable gets clipped in width and height based on the level, as well as a gravity to control where it is placed in its overall container. Most often used to implement things like progress bars, by increasing the drawable's level with setLevel().
一種能夠根據當前的level值來裁剪出另外一個Drawable的Drawable,能夠經過調節level值來控制裁剪的寬和高,以及裁剪內容佔整個容器的權重,常常經過Drawable的setLevel()方法來增長顯示比例以實現相似進度條的效果。 level的範圍是0~10000,在ClipDrawable中,0表示的是徹底裁剪,即整個Drawable都不可見,10000表示不裁剪。 相關的源碼以下:
int w = bounds.width(); final int iw = 0; //mState.mDrawable.getIntrinsicWidth(); if ((mState.mOrientation & HORIZONTAL) != 0) { w -= (w - iw) * (MAX_LEVEL - level) / MAX_LEVEL; } int h = bounds.height(); final int ih = 0; //mState.mDrawable.getIntrinsicHeight(); if ((mState.mOrientation & VERTICAL) != 0) { h -= (h - ih) * (MAX_LEVEL - level) / MAX_LEVEL; }
在xml文件中使用<clip>根節點來建立ClipDrawable,屬性以下: | 屬性名 | 功能 | | ------ | :---- | | android:clipOrientation | 裁剪的方向(horizontal、vertical) | | android:drawable | 引用一個drawable資源 | | android:gravity | 指定在drawable中剪切的位置|
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="vertical" android:drawable="@drawable/image1" android:gravity="bottom" />
<ImageView android:id = "@+id/iv_clip" android:layout_width = "100dp" android:layout_height = "100dp" android:src = "@drawable/clip_drawable" />
ImageView iv = findViewById(R.id.iv_clip); ClipDrawable clipDrawable = (ClipDrawable)iv.getDrawable(); clipDrawable.setLevel(2000); //裁剪80%的區域
自定義ClipDrawable,主要是重寫draw(Canvas canvas)方法;
使用樣例: (實現圓形加載進度條)
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@mipmap/circle" android:gravity="bottom" android:clipOrientation="vertical" > </clip>
<android.support.constraint.ConstraintLayout 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="match_parent" tools:context=".activity.SearchActivity" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/iv_clip" android:src="@drawable/clip_drawable" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> //顯示進度 <TextView android:id="@+id/tv_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:textColor="#de000000" android:text="0%" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> </android.support.constraint.ConstraintLayout>
private Timer timer; private TimerTask timerTask; private ClipDrawable clipDrawable; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what != 0) { clipDrawable.setLevel(msg.what); tv_progress.setText(String.valueOf(msg.what*100/10000)+"%"); } else { clipDrawable.setLevel(0); tv_progress.setText("0%"); } } } @Override protected void onCreate(Bundle savedInstanceState) { ... clipDrawable = (ClipDrawable)iv_clip.getDrawable(); clipDrawable.setLevel(0); timer = new Timer(); timerTask = new TimerTask() { @Override public void run() { if (clipDrawable.getLevel() <= 10000) { handler.sendEmptyMessage(clipDrawable.getLevel()+25); } else { handler.setEmptyMessage(0); } } }; timer.schedule(timerTask,1000,50); } @Override protected void onDestroy() { super.onDestroy(); if (timer != null) { timer.cancel(); timer.purge(); timer = null; } }
效果圖以下: ==>
Lets you assign a number of graphic images to a single Drawable and swap out the visible item by a string ID value.
StateListDrawable能夠根據view的不一樣狀態來展現不一樣的drawable;例如一個按鈕不點擊時背景爲綠色,點擊後變爲橙色,用來動態設置TextView、Button、ImageView等組件在不一樣狀態下的背景/前景顯示效果;
StateListDrawable對應的xml根元素爲<selector>,而每一個selector中能夠放置多個item元素,每一個item元素能夠設置如下兩個屬性:
Transition是一個特殊的Drawable對象,能夠實現兩個drawable資源之間淡入淡出的效果。 xml屬性以下: | 屬性名| 描述 | |----|:---| |android:drawable| 用來渲染圖層的drawable資源| |android:left| 圖層的左側座標| |android:top| 圖層的頂部座標| |android:right|圖層的右側座標| |android:bottom|圖層的底部座標| |android:id|圖層的標識符|
使用方式:
<transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable = "@mipmap/pic_first" /> <item android:drawable = "@mipmap/pic_second" />
<ImageView android:id = "@+id/iv_transition" android:layout_width = "100dp" android:layout_height = "100dp" />
ImageView iv = findViewById(R.id.iv_transition); TransitionDrawable transition = (TransitionDrawable)getResources().getDrawable(R.drawable.transition_simple); iv.setImageDrawable(transition); transition.startTransition(2000);
須要調用startTransition()方法才能啓動兩層間的切換動畫;也能夠調用reverseTransition()方法反過來播放。
InsetDrawable表示一個drawable根據指定的距離嵌入到另一個drawable內部。(咱們看到的仍是同一張圖片,只是會空出一些邊距);當控件須要的背景比實際的邊框小的時候比較適合使用InsetDrawable; 在xml文件中經過<inset>做爲根元素來建立InsetDrawable,具體的屬性值以下: | 屬性 | 描述 | | ---- | :----| | android:drawable|引用的drawable資源| | android:insetTop|與頂部的距離 | | android:insetBottom|與底部的距離| | android:insetLeft|與左側的距離| | android:insetRight|與右側的距離|
使用:
<?xml version="1.0" encoding="utf-8"?> <inset xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/guess_you_like_bg" android:insetTop="20dp" android:insetBottom="20dp" android:insetLeft="20dp" android:insetRight="20dp"/>
<ImageView android:id = "@+id/iv_show" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/inset" />