【Android Drawable】二姜骡、BitmapDrawable、NinePatchDrawable屿良、GradientDrawable圈澈、StateListDrawable

一、BitmapDrawable

Bitmap 是一種位圖圖像尘惧,Android 系統(tǒng)支持三種格式的位圖圖像康栈,.png (preferred)(支持最好),.jpg (acceptable)喷橙, .gif (discouraged)(支持最差)啥么。

在構(gòu)建應(yīng)用的時候,Bitmap文件可能會被appt工具壓縮自動優(yōu)化為無損圖像贰逾。例如,一個真彩色PNG悬荣,不需要超過256的顏色可以被轉(zhuǎn)換成一個8位PNG和調(diào)色板。這將導(dǎo)致一個圖像質(zhì)量相同疙剑,但這需要更少的內(nèi)存氯迂。所以要意識到,在drawable目錄中圖像的二進(jìn)制文件在構(gòu)建程序時可以改變言缤。如果你打算讀一個圖像作為字節(jié)流并將它轉(zhuǎn)換成一個位圖嚼蚀,把你的圖片放在在res /raw/文件夾里,在那里他們不會被優(yōu)化管挟。

屬性介紹
    android:src=""
    android:alpha=""
    android:antialias=""
    android:autoMirrored=""
    android:dither=""
    android:filter=""
    android:gravity=""
    android:mipMap=""
    android:tileMode=""
    android:tileModeX=""
    android:tileModeY=""
    android:tint=""
    android:tintMode=""
  • android:antialias 抗鋸齒

開啟抗鋸齒轿曙,圖像會變的=得更平滑,但是會降低清晰度僻孝,一般開啟拳芙;

  • android:dither 防抖動

讓高質(zhì)量的圖片的比較低質(zhì)量的屏幕上不失真,得到比較好的顯示效果皮璧。
比如圖片的色彩模式是 ARGB8888舟扎,但是手機設(shè)備的支持RGB555的色彩模式,那么開啟這么就可以有效減少失真現(xiàn)象悴务。
(Android中我們創(chuàng)建的Bitmap一般會選擇ARGB888模式睹限,ARGB每個通道各占8位譬猫,8位1個字節(jié),一個像素4個字節(jié)羡疗,一個像素的位數(shù)總和越高染服,圖片越逼真)

  • android:filter 過濾效果

在圖片圖片被拉伸或者壓縮的時候開啟過濾效果可以顯示更加好的效果。

  • android:mipmap

紋理映射

  • android:gravity 圖片位置
    可選項
  • top|bottom|left|right|center|center_vertical|center_horizontal|cneter 保持圖片原來大小
  • fill_vertical|fill_horizontal|fill 拉伸圖片填充容器叨恨,BitmapDrawable 作為背景時會自動拉伸為 View 寬高柳刮,所以默認(rèn)的 gravity 屬性值為 fill
  • clip_vertical | clip_horizontal 附加項,表示裁剪圖片
  • android:tileMode 平鋪模式

默認(rèn)為 disabled痒钝,不為 disabled 時秉颗,gravity 屬性會被忽略

  • disabled 關(guān)閉平鋪模式
  • clamp 拉伸像素
  • repeat 水平和垂直方向平鋪
  • mirror 鏡像平鋪
BitmapDrawable 內(nèi)部寬高
    @Override
    public int getIntrinsicWidth() {
        return mBitmapWidth;
    }

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

可以看到 BitmapDrawable 返回的寬高就是 Bitmap 的寬高,Bitmap 的寬高是在 computeBitmapSize() 方法中賦值的:

private void computeBitmapSize() {
        final Bitmap bitmap = mBitmapState.mBitmap;
        if (bitmap != null) {
            mBitmapWidth = bitmap.getScaledWidth(mTargetDensity);
            mBitmapHeight = bitmap.getScaledHeight(mTargetDensity);
        } else {
            mBitmapWidth = mBitmapHeight = -1;
        }
    }

如果 mBitmapState 中的成員變量 mBitmap 不為 null 的話送矩,把 mTargetDensity 作為參數(shù)調(diào)用 Bitmap 的 getScaledXXX 方法蚕甥。
這里的 mTargetDensity 是 Drawable 的目標(biāo)密度,在構(gòu)造方法中會進(jìn)行賦值栋荸,也可以通過 setTargetDensity 方法賦值菇怀,默認(rèn)為設(shè)備的屏幕像素密度。
Bitmap 也有一個成員變量 mDensity 是自身的像素密度晌块,在 getScaledXXX 方法中會根據(jù) mTargetDensity / mDensity 對 Bitamp 的寬高尺寸進(jìn)行縮放爱沟。

public int getScaledHeight(int targetDensity) {
        return scaleFromDensity(getHeight(), mDensity, targetDensity);
    }

    /**
     * @hide
     */
    static public int scaleFromDensity(int size, int sdensity, int tdensity) {
        if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
            return size;
        }

        // Scale by tdensity / sdensity, rounding up.
        return ((size * tdensity) + (sdensity >> 1)) / sdensity;
    }
Bitmap 和 Drawable 的轉(zhuǎn)換
  1. Bitmap --> Drawable:
    new BitampDrawable(bitmap)

二、NinePatchDrawable

.9格式的圖片匆背。BitmapDrawable 會根據(jù) View 的大小進(jìn)行拉伸呼伸,而.9圖片可自動地根據(jù)所需的寬/高進(jìn)行相應(yīng)的縮放并保證不失真。
同樣可以通過 xml 文件來描述靠汁,屬性同 bitmap

三蜂大、ShapeDrawable & GradientDrawable

屬性
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle|oval|line|ring"
    android:innerRadius=""
    android:innerRadiusRatio=""
    android:thickness=""
    android:thicknessRatio=""
    android:useLevel="">
    <corners android:radius=""
        android:topLeftRadius=""
        android:topRightRadius=""
        android:bottomLeftRadius=""
        android:bottomRightRadius=""/>
    <gradient
        android:type="linear|radio|sweep"
        android:startColor=""
        android:centerColor=""
        android:endColor=""
        android:centerX=""
        android:centerY=""
        android:angle=""
        android:gradientRadius=""
        android:useLevel=""/>
    <padding android:top=""
        android:bottom=""
        android:left=""
        android:right=""/>
    <size
        android:width=""
        android:height=""/>
    <solid
        android:color=""/>
    <stroke
        android:color=""
        android:width=""
        android:dashWidth=""
        android:dashGap=""/>
</shape>
  • android:shape 默認(rèn)為 rectangle闽铐,line 和 ring 必須通過標(biāo)簽<stroke> 來指定寬度和顏色蝶怔;
    當(dāng) shape 為 ring 時,有五個特殊屬性:
  • android:innerRadius 圓環(huán)內(nèi)半徑兄墅,會覆蓋 innerRadiusRatio踢星;
  • android:innerRadiusRatio 圓環(huán)內(nèi)半徑所占比率,默認(rèn)為9隙咸;
  • android:thickness 圓環(huán)厚度沐悦,會覆蓋 thicknessRaio;
  • android:thicknessRatio 圓環(huán)厚度所占比率五督,默認(rèn)為3藏否;
  • android:useLevel 常為false,除非它被當(dāng)做是LevelListDrawable充包;
  • <corners>:表示shape的四個圓角的角度副签,只適用于矩形遥椿。
  • <gradient>:漸變效果,與 <solid> 的純色填充相互排斥淆储。
  • android:type:漸變的類別冠场。有l(wèi)inear(線性漸變)、radial(徑向漸變)本砰、sweep(掃描線漸變)碴裙,默認(rèn)為linear。
  • android:centerX:漸變的中心點的X坐標(biāo)点额。
  • android:centerY:漸變的中心點的Y坐標(biāo)舔株。
  • android:gradientRadius :漸變半徑。僅當(dāng)android:type="radial"時有效咖楣。
  • android:angle:漸變角度督笆,默認(rèn)為0,必須為45的倍數(shù)诱贿,0表示從左到右娃肿,90表示從上到下,僅在 linear 時有效
  • <stroke>:描邊珠十。
  • android:width:描邊的寬度料扰。
  • android:color:描邊的顏色。
  • android:dashWidth:虛線的寬度焙蹭。
  • android:dashGap:虛線之間的間隔晒杈。
  • <solid> :填充純色
  • <padding> :內(nèi)邊距
  • <size>:大小。其android:width和android:height分別設(shè)定shape的寬/高孔厉。注意拯钻,這個表示的是shape的固有大小,但并不是其最終大小撰豺。
用代碼創(chuàng)建

通過 inflate 方法解析 xml 文件中的屬性粪般,也可以使用構(gòu)造方法來創(chuàng)建 ShapeDrawable 對象:

public ShapeDrawable()
public ShapeDrawable(Shape s)
private ShapeDrawable(ShapeState state, Resources res)

ShapeDrawable 有三個構(gòu)造方法,第一個沒有參數(shù)污桦,第二個傳入一個 Shape 對象亩歹,最終都是調(diào)用了第三個,但是第三個構(gòu)造方法是 private 修飾的凡橱,第三個方法的第一個參數(shù)是一個 ShapeState 對象小作,ShapeState 類繼承自 Drawable 類的靜態(tài)內(nèi)部類 ConstantState ,ShapeState 封裝了當(dāng)前 Drawable 的重要屬性稼钩, ShapeState是Drawable 自己的保存狀態(tài)量和數(shù)據(jù)的重要對象.顾稀。在該方法中給 ShapeDrawable 的成員變量 mShapeState 賦值,并初始化 PorterDuffColorFilter 類型成員變量 mTintFilter坝撑。
但是其實 <shape> 標(biāo)簽定義的不是 ShapeDrawable 而是 GradientDrawable静秆。
Drawable 類也有三個構(gòu)造方法:

public GradientDrawable()
public GradientDrawable(Orientation orientation, @ColorInt int[] colors)
private GradientDrawable(@NonNull GradientState state, @Nullable Resources res)

最終都是調(diào)用了 private 的兩個參數(shù)的構(gòu)造方法氮块,第一個參數(shù)是 ConstantState 的子類 GradientState,第二個參數(shù)還是 Resources 對象诡宗。
GradientState 的構(gòu)造方法有兩個:

public GradientState(Orientation orientation, int[] gradientColors) {
            mOrientation = orientation;
            setGradientColors(gradientColors);
 }
public GradientState(@NonNull GradientState orig, @Nullable Resources res)

也就是說滔蝉,在創(chuàng)建 GradientState 時,必須要確定漸變的方向和漸變顏色:
Orientation 是一個內(nèi)部枚舉類:

public enum Orientation {
        TOP_BOTTOM, //從上到下 angle = 90
        TR_BL,//從右上到左下   angle = 135
        RIGHT_LEFT,//從右向左 angle = 180
        BR_TL,//從右下到左上  angle = 225
        BOTTOM_TOP,//從下到上 angle = 270
        BL_TR,//從左下到右上  angle = 315
        LEFT_RIGHT,//從左到右   angle = 0
        TL_BR,//從左上到右下 angle = 45
    }
public void setGradientColors(@Nullable int[] colors) {
            mGradientColors = colors;
            mSolidColors = null;
            computeOpacity();
        }

<solid> 標(biāo)簽和 <gradient> 標(biāo)簽相互沖突塔沃,以及 <stroke> 標(biāo)簽定義的屬性分別存儲在以下三個成員變量中

        public ColorStateList mSolidColors; 
        public ColorStateList mStrokeColors;
        public @ColorInt int[] mGradientColors;

GradientDrawable 類對外提供了一系列方法設(shè)置相關(guān)屬性:

  • <shape>
    setShape(@Shape int shape)蝠引,參數(shù)為 GradientDrawable 內(nèi)部定義的 int 類型常量
  • <corners>
    setCornerRadius(float radius)
    setCornerRadii(@Nullable float[] radii)
  • <gradient>
    setGradientType(@GradientType int gradient) 參數(shù)也為靜態(tài)常量
    setGradientCenter(float x, float y)
    setGradientRadius(float gradientRadius)
  • <solid>
    setColor(@ColorInt int argb)
    setColor(@Nullable ColorStateList colorStateList)
  • <stroke>
    setStroke(int width, @ColorInt int color)
    setStroke(int width, ColorStateList colorStateList)
    setStroke(int width, @ColorInt int color, float dashWidth, float dashGap)
    setStroke(
    int width, ColorStateList colorStateList, float dashWidth, float dashGap)
  • <size>
    setSize(int width, int height)

四、StateListDrawable

下面羅列了 selector 的所有 state蛀柴,android:drawable 屬性引用drawable 資源螃概,也可以在 <item> 標(biāo)簽中定義其它 drawable 。
android:contantSize 屬性為 true 時鸽疾,StateListDrawable 固有大小保持不變吊洼,是內(nèi)部所有 Drawable 的固有大小的最大值。false 則會隨著狀態(tài)的改變而改變制肮;
android:variablePadding 屬性為 true 時表示 padding 隨著狀態(tài)改變而改變冒窍,為 false 表示 padding 為內(nèi)部所有 drawable 的 padding 最大值保持不變;

<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:constantSize=""
    android:variablePadding="">
    <item android:state_accelerated=""
        android:state_active=""
        android:state_activated=""
        android:state_checkable=""
        android:state_checked=""
        android:state_drag_can_accept=""
        android:state_drag_hovered=""
        android:state_enabled=""
        android:state_first=""
        android:state_focused=""
        android:state_hovered=""
        android:state_last=""
        android:state_middle=""
        android:state_pressed=""
        android:state_selected=""
        android:state_single=""
        android:state_window_focused=""
        android:drawable="">
          <color android:color=""/>
          <bitmap android:src=""/>
          <nine-patch android:src=""/>
          <clip android:drawable="" />
          <inset android:drawable="" />
          <scale android:drawable=""/>
          <ripple android:color=""/>
          <rotate android:drawable=""/>
          <transition />
          <layer-list></layer-list>
          <level-list></level-list>
          <shape ></shape>
          <selector></selector>
         <animation-list></animation-list>
         <animated-rotate />
         <animated-selector android:fromId="" android:toId=""/>
    </item>
</selector>

StateListDrawable 類有三個構(gòu)造方法:

public StateListDrawable() 
private StateListDrawable(StateListState state, Resources res)
StateListDrawable(@Nullable StateListState state)

構(gòu)造方法傳入了一個 StateListState 參數(shù)豺鼻,這個 StateListState 不是繼承自 Drawable.ConstantState 類综液,而是繼承自 DrawableContainer.DrawableContainerState 類,它的構(gòu)造方法是 StateListState(StateListState orig, StateListDrawable owner, Resources res)
構(gòu)造方法內(nèi)部都是創(chuàng)建一個 StateListState 對象儒飒,然后調(diào)用了 setConstantState(DrawableContainerState state) 方法給 成員變量 mStateListState 賦值谬莹。
StateListState 內(nèi)部有一個二維數(shù)組 mStateSets 保存著所有的狀態(tài)和 Drawable。給 StateListDrawable 添加 item 就是通過調(diào)用 addState 方法桩了,state 是放在一個 int 數(shù)組里面的附帽。

public void addState(int[] stateSet, Drawable drawable) {
        if (drawable != null) {
            mStateListState.addStateSet(stateSet, drawable);
            // in case the new state matches our current state...
            onStateChange(getState());
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市井誉,隨后出現(xiàn)的幾起案子蕉扮,更是在濱河造成了極大的恐慌,老刑警劉巖送悔,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慢显,死亡現(xiàn)場離奇詭異爪模,居然都是意外死亡欠啤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門屋灌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洁段,“玉大人,你說我怎么就攤上這事共郭§羲浚” “怎么了疾呻?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長写半。 經(jīng)常有香客問我岸蜗,道長,這世上最難降的妖魔是什么叠蝇? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任璃岳,我火速辦了婚禮,結(jié)果婚禮上悔捶,老公的妹妹穿的比我還像新娘铃慷。我一直安慰自己,他們只是感情好蜕该,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布犁柜。 她就那樣靜靜地躺著,像睡著了一般堂淡。 火紅的嫁衣襯著肌膚如雪馋缅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天绢淀,我揣著相機與錄音股囊,去河邊找鬼。 笑死更啄,一個胖子當(dāng)著我的面吹牛稚疹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播祭务,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼内狗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了义锥?” 一聲冷哼從身側(cè)響起柳沙,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤朱转,失蹤者是張志新(化名)和其女友劉穎澳泵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棍掐,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡柱恤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年数初,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梗顺。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡泡孩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出寺谤,到底是詐尸還是另有隱情仑鸥,我是刑警寧澤吮播,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站眼俊,受9級特大地震影響意狠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜疮胖,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一摄职、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧获列,春花似錦谷市、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至巩梢,卻和暖如春创泄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背括蝠。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工鞠抑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人忌警。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓搁拙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親法绵。 傳聞我的和親對象是個殘疾皇子箕速,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容