安卓學習筆記之Drawable

1 Drawable基礎

1.1什麼是Drawable

首先Drawable是一個抽象類,表示的是可以在Canvas中繪製的圖像,常被用作一個view的背景,有多種實現類完成不同的功能。其次Drawable大致可以分爲這幾類:圖片、由顏色構成的圖像。一般用xml中進行定義。

1.2 Drawable的繼承體系

這裏寫圖片描述

1.3 Drawable的實現類及標籤

這裏寫圖片描述
圖片來源於網絡。

1.4 Drawable內部寬高的獲取

使用方法getIntrinsicWidth、getIntrinsicHeight來獲取寬高

  • 當Drawable由圖片構成時方法返回的是圖片的寬高
  • 當Drawable由顏色構成時則沒有寬高的概念,返回-1

2 各類Drawable及其用法

2.1 BitmapDrawable

用於顯示一張圖片,如下示例

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:antialias="true"
    android:dither="true"
    android:filter="true"
    android:gravity="top"
    android:src="@mipmap/girl"
    android:tileMode="repeat" />

常用屬性

android:antialias 是否開啓抗鋸齒
android:dither 是否開啓防抖動
android:filter 是否開啓過濾效果
android:gravity 用於對圖片進行定位
android:src 圖片資源id
android:tileMode 平鋪模式,repeat、mirror、clamp三種 

2.2 ColorDrawable

代表了單色可繪製區域,包裝了一種固定的顏色,在畫布上繪製一塊單色的區域。

示例:

<?xml version="1.0" encoding="utf-8"?>
<color xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/colorAccent">
</color>

還可以用代碼創建

ColorDrawable drawable = new ColorDrawable(int color); //傳入一個color的integer值

2.3 NinePatchDrawable

即9-patch圖,可以根據內容進行自由縮放寬高而不失真

示例:

<?xml version="1.0" encoding="utf-8"?>
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
    android:dither="true"
    android:filter="true"
    android:src="@color/colorAccent">
</nine-patch>

用draw9patch設定縮放區域

圖中1、2方向表示在draw9patch中繪製黑線,黑線長度交集爲可拉伸的範圍
圖中3、4方向黑線長度交集表示內容可以填充的區域
這裏寫圖片描述

2.4 ShapeDrawable

通過顏色來構造圖形,既可以爲純色圖形,也可以爲具有漸變效果的圖形。能構成的圖形有rectangle、oval、ring、line

具有漸變效果的圓示例:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <gradient
        android:angle="45"
        android:centerColor="@color/colorAccent"
        android:centerX="50%"
        android:centerY="50%"
        android:endColor="@color/colorPrimary"
        android:gradientRadius="150dp"
        android:startColor="@color/colorPrimaryDark"
        android:type="sweep" />
    <size
        android:width="260dp"
        android:height="260dp" />
</shape>

注意:1、android:angle值必須爲45的倍數 2、oval用於繪製橢圓,當size的寬高相等時繪製成圓

圓環示例:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:innerRadius="100dp"
    android:shape="ring"
    android:thickness="10dp"
    android:useLevel="false" >

    <stroke
        android:width="10dp"
        android:color="@color/colorAccent" />
</shape>

注意:

  • 1、android:useLevel設置爲false,否則無法顯示理想效果
  • 2、innerRadius爲圓環內半徑,innerRadiusRation爲內半徑佔圓環寬度的比率,兩者以innerRadius爲主
  • 3、thickness爲圓環的寬度,thicknessRatio爲此寬度佔圓環寬度的比率,以thickness爲主

常用屬性

  • android:shape 要繪製的形狀,rectangle、oval、ring、line

  • stroke 形狀的描邊,有如下屬性

    • android:width 描邊的寬度
    • android:color 描邊的顏色
    • android:dashGap 繪製虛線的線寬
    • android:dashWidth 繪製虛線的線段間隔 (要繪製虛線,後兩者均不能爲0)
  • solid 純色填充,android:color指定shape顏色

  • gradient 漸變效果,與solid不可一起用,有如下屬性

    • android:angle 漸變的角度,必須爲45的倍數
    • android:startColor 漸變的起始顏色
    • android:centerColor 漸變的中間顏色
    • android:endColor 漸變的結束顏色
    • android:centerX 漸變的中心點橫座標
    • android:centerY 漸變的中心點縱座標
    • android:gradientRadius 漸變半徑
    • android:type 漸變類型,linear(線性)、sweep(掃視)、radial(徑向)
  • corners 表示矩形(rectangle)的四個角的角度,不適用於其他shape ,有如下屬性

    • android:topLeftRadius、android:topRightRadius、android:bottomLeftRadius、android:bottomRightRadius 分別爲設置左上角、右上角、左下角、右下角的角度
    • android:radius 爲四角設置相同角度,優先級低,會被其他四個屬性覆蓋
  • size shape的寬高,對應着android:width、android:height

    • shape默認無寬高,getIntrinsicHeight、getIntrinsicWidth返回-1
    • 通過size可以設置其寬高,但作爲view背景時任然會被拉伸或縮小爲 view大小
  • padding 設置容納shape的view的空白間距

2.5 StateListDrawable

可以看作是一個狀態選擇器,通過view不同的狀態選擇對應的item中的drawable顯示

示例:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/colorPrimaryDark" android:state_pressed="false"></item>
    <item android:drawable="@color/colorAccent" android:state_pressed="true"></item>
</selector>

常見狀態

android:state_pressed 當按住一個view時,按下的狀態
android:state_checked  當一個view被選中時,適用於CheckBox
android:state_selected  當一個view被選擇時
android:state_enabled  當一個view處於可用狀態
android:state_focused  當view獲取焦點

2.6 LayerDeawable

表示的是一種分層的的Drawable集合,類似於ps中的圖層的概念,將多個drawable放在不同的層上面形成一種疊加的效果

示例:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/night" />
    <item
        android:drawable="@mipmap/photo6"
        android:gravity="center" />
</layer-list>

注意事項:

  • 1、layer-list可以包含多個item,每個item表示一個drawable,並且後添加的item會覆蓋到之前添加的item上面
  • 2、默認情況下,layer-list所有的drawable都會縮放至view大大小,通過設施android:gravity可以調節縮放的效果
  • 3、可以設置上下左右偏移量,android:top、android:bottom、android:left、android:right

2.7 LevelListDrawable

表示一個drawable集合,集合中的每一個Drawable都有一個等級(level),通過設置不同的等級,可以使LevelListDrawable切換至不同的Drawable。等級範圍在0~10000之間, android:maxLevel設置最大level, android:minLevel設置最小level
示例:

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@mipmap/photo0"
        android:maxLevel="20"
        android:minLevel="10" />
    <item
        android:drawable="@mipmap/photo1"
        android:maxLevel="40"
        android:minLevel="30" />
</level-list>

通過設置level可以切換不同的Drawable,在代碼中

    //將ImageView的背景切換爲photo1, 35 在30~40之間
    iv.setImageLevel(35); 
    //將ImageView的背景切換爲photo0, 15在10~20之間
    iv.setImageLevel(15); 

2.8 TransitionDrawable

LayerDeawable的子類,用於實現連個Drawable的淡入淡出效果
示例:
xml文件定義

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/night" />
    <item android:drawable="@mipmap/photo6" />
</transition>

給ImageView設置src,在java代碼中

    iv= (ImageView) findViewById(R.id.iv_transition);
    drawable = (TransitionDrawable) iv.getDrawable();
    drawable.startTransition(1000); // 實現淡入淡出效果
    drawable.reverseTransition(1000);

2.9 InsetDrawable

嵌入其他Drawable,並可以在四周保留一定的間距
示例:

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@mipmap/photo6"
    android:inset="20dp">
</inset>

2.10 ScaleDrawable

根據等級將一個Drawable縮放到一定的比例,當level爲0時不可見,當level爲10000時無縮放效果
示例:

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@mipmap/night"
    android:scaleGravity="center"
    android:scaleHeight="50%"
    android:scaleWidth="50%" />

要顯示出效果,必須設置level大於0

   iv = (ImageView) findViewById(R.id.iv_scale);
   ScaleDrawable drawable= (ScaleDrawable) iv.getDrawable();
   drawable.setLevel(1);
- android:scaleHeight="percentage",android:scaleWidth="percentage",設置寬高縮放爲原來的比例爲(100%-percentage)
- 設置level越大,圖像顯示越大

2.11 ClipDrawable

根據自己的等級(level)來對另一個Drawable進行裁剪,裁剪的方向由android:clipOrientation、android:gravity共同決定。設置level進行裁剪,level的大小從0到10000,level爲0時完全不顯示,爲10000時完全顯示
xml定義

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:drawable="@mipmap/night"
    android:gravity="right"></clip>

設置給ImageView

<ImageView
     android:id="@+id/iv_clip"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:src="@drawable/drawable_clip" />

通過設置level來裁剪

    ImageView iv = (ImageView) findViewById(R.id.iv_clip);
    ClipDrawable drawable= (ClipDrawable) iv.getDrawable();
    drawable.setLevel(5000); //  設置的level越大裁剪的範圍越小

屬性

android:clipOrientation ,horizontal 水平方向裁剪,vertical 垂直方向裁剪
android:gravity ,配合裁剪方向

這裏寫圖片描述


3 自定義Drawable

3.1 自定義Drawable的一般步驟

  1. 自定義Drawable類繼承自Drawable
  2. 實現getOpacity,setColorFilter,setAlpha等方法
  3. 在onDraw方法中進行繪製
  4. 若自定義的Drawable有固定的大小,則需實現getIntrinsicWidth、getIntrinsicHeight方法

3.2 自定義圓形Drawable

package com.yu.drawablelearing;

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;

public class CircleDrawable extends Drawable{

    private int radius;
    private int mWidth;
    private int mHeight;
    private Paint mPaint;
    @Override
    public void draw(Canvas canvas) {
        canvas.drawCircle(mWidth/2,mHeight/2,radius,mPaint);
    }

    public CircleDrawable(Bitmap bitmap) {
        radius = Math.min(bitmap.getWidth(), bitmap.getHeight())/2;
        mWidth = bitmap.getWidth();
        mHeight = bitmap.getHeight();
        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mPaint = new Paint();
        mPaint.setShader(bitmapShader);
        mPaint.setAntiAlias(true);

    }
    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
        invalidateSelf();
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mPaint.setColorFilter(colorFilter);
        invalidateSelf();
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public int getIntrinsicHeight() {
        return mHeight;
    }

    @Override
    public int getIntrinsicWidth() {
        return mWidth;
    }
}

3.3 自定義帶圓角的矩形Drawable

package com.yu.drawablelearing;

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;

/**
 * Created by pecu on 2016/08/24.
 */
public class RoundRectangleDrawable extends Drawable {
    private RectF rectF;
    private Paint mPaint;
    Bitmap mBitmap;
    @Override
    public void draw(Canvas canvas) {
        canvas.drawRoundRect(rectF, mBitmap.getWidth()/6,mBitmap.getHeight()/6, mPaint);
    }

    public RoundRectangleDrawable(Bitmap bitmap) {
        mBitmap = bitmap;
        mPaint = new Paint();
        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mPaint.setAntiAlias(true);
        mPaint.setShader(bitmapShader);
    }
    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
        invalidateSelf();
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mPaint.setColorFilter(colorFilter);
        invalidateSelf();

    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, bottom);
        rectF = new RectF(left, top, right, bottom);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public int getIntrinsicWidth() {
        return mBitmap.getWidth();
    }

    @Override
    public int getIntrinsicHeight() {
        return mBitmap.getHeight();
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章