Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android入門——Drawable與對應的資源xml的應用

Android入門——Drawable與對應的資源xml的應用

編輯:關於android開發

Android入門——Drawable與對應的資源xml的應用


引言

Android 中的Drawable是一個抽象的概念,換言之所有能被畫出來的都可以定義成Drawable(A Drawable is a general abstraction for “something that can be drawn.” )。所以Android應用中使用最為廣泛和最靈活的資源,不僅僅可以直接使用.png、.9.png、.gif、.jpg等圖片作為資源,還可以使用多種XML文件。

一、Drawable概述

Drawable同時也是一個抽象類,我們在Android開發中不直接使用,往往都是使用它的派生類,常見的派生類有:BitmapDrawable, ClipDrawable, ColorDrawable, DrawableContainer, GradientDrawable, InsetDrawable, LayerDrawable, NinePatchDrawable, PictureDrawable, RotateDrawable, ScaleDrawable, ShapeDrawableAnimationDrawable, LevelListDrawable, PaintDrawable, StateListDrawable, TransitionDrawable。在程序中我們可以通過Resource類的getDrawable(int id,int theme)獲取對應的Drawable對象。

二、Drawable系的應用

1、StateListDrawable(selector xml文件)

說起selector xml文件大家都知道,但是StateListDrawable我相信有相當數量的人員不一定了解。StateListDrawable可以用於組織多個Drawable對象,常被用於view的背景、前景,當view的狀態改變的時候而自動切換。

1.1、StateListDrawable對象的xml文件結構

對應的根元素為selector,可以包含多個item元素

android:color或者android:drawable:可設置指定顏色或Drawable對象 adnroid:state_xxx:一個特定的狀態 狀態屬性值 含義 android:state_active 是否處於激活狀態 android:state_checkable 是否可勾選 android:state_checked 是否已勾選 android:state_enabled 是否可用 android:state_first 是否開始狀態 android:state_focused 是否已得到焦點 android:state_last 是否處於結束 android:state_middle 是否處於中間 android:state_pressed 是否處於按下狀態 . android:state_selected 是否處於選中狀態 android:state_window_focused 是否窗口已獲得焦點

例:selector_mybutton.xml

<code class=" hljs xml"><!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%20%3F%2D%2D%3E-->   
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
<!--{cke_protected}{C}%3C!%2D%2D%20%E9%BB%98%E8%AE%A4%E6%97%B6%E7%9A%84%E8%83%8C%E6%99%AF%E5%9B%BE%E7%89%87%2D%2D%3E-->  
  <item android:drawable="@drawable/pic1">    
<!--{cke_protected}{C}%3C!%2D%2D%20%E6%B2%A1%E6%9C%89%E7%84%A6%E7%82%B9%E6%97%B6%E7%9A%84%E8%83%8C%E6%99%AF%E5%9B%BE%E7%89%87%20%2D%2D%3E-->  
  <item android:state_window_focused="false" android:drawable="@drawable/pic_nofocus">   
<!--{cke_protected}{C}%3C!%2D%2D%20%E9%9D%9E%E8%A7%A6%E6%91%B8%E6%A8%A1%E5%BC%8F%E4%B8%8B%E8%8E%B7%E5%BE%97%E7%84%A6%E7%82%B9%E5%B9%B6%E5%8D%95%E5%87%BB%E6%97%B6%E7%9A%84%E8%83%8C%E6%99%AF%E5%9B%BE%E7%89%87%20%2D%2D%3E-->  
  <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/pic_click"> 
<!--{cke_protected}{C}%3C!%2D%2D%20%E8%A7%A6%E6%91%B8%E6%A8%A1%E5%BC%8F%E4%B8%8B%E5%8D%95%E5%87%BB%E6%97%B6%E7%9A%84%E8%83%8C%E6%99%AF%E5%9B%BE%E7%89%87%2D%2D%3E-->  
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/pic_touch">  
<!--{cke_protected}{C}%3C!%2D%2D%E9%80%89%E4%B8%AD%E6%97%B6%E7%9A%84%E5%9B%BE%E7%89%87%E8%83%8C%E6%99%AF%2D%2D%3E-->  
  <item android:state_selected="true" android:drawable="@drawable/pic_select">   
<!--{cke_protected}{C}%3C!%2D%2D%E8%8E%B7%E5%BE%97%E7%84%A6%E7%82%B9%E6%97%B6%E7%9A%84%E5%9B%BE%E7%89%87%E8%83%8C%E6%99%AF%2D%2D%3E-->  
  <item android:state_focused="true" android:drawable="@drawable/pic_getfocus">   
</item></item></item></item></item></item></selector></code>

2、LayerDrawable(layer-list xml文件)

LayerDrawable與StateListDrawable類似,也可以包含一個Drawable數組,系統將會按這些Drawable對象的數組順序來繪制,索引最大的Drawable將會被繪制在最上面。

2.1、LayerDrawable對象的xml文件結構

其根節點是layer-list,也可以包含多個item元素:

android:drawable:指定要包含的Drawable對象 android:id:Drawable的Id adnroid:buttom | top | left | button:用於指定一個長度值,指定該Drawable對象繪制到目標組件的指定位置。

2.2、在xml中實現LayerDrawable

<code class=" hljs xml"><!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%2D%2D%3E-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!--{cke_protected}{C}%3C!%2D%2D%E6%9C%80%E5%BA%95%E5%B1%82%2D%2D%3E-->
    <item>
        <bitmap android:src="@mipmap/ic_blue_launcher" android:gravity="center">
    </bitmap></item>
    <!--{cke_protected}{C}%3C!%2D%2D%E6%AC%A1%E4%B8%8A%E5%B1%82%2D%2D%3E-->
    <item android:top="10dp" android:left="10dp">
        <bitmap android:src="@mipmap/ic_red_launcher" android:gravity="center">
    </bitmap></item>
    <!--{cke_protected}{C}%3C!%2D%2D%E6%98%BE%E7%A4%BA%E5%9C%A8%E6%9C%80%E4%B8%8A%E9%9D%A2%2D%2D%3E-->
    <item android:top="20dp" android:left="20dp">
        <bitmap android:src="@mipmap/ic_green_launcher" android:gravity="center">
    </bitmap></item>
</layer-list></code>

2.3、在Java代碼中動態生成並使用

Resources resources = getResources();   
Drawable[] layers = new Drawable[3];   
layers[0] = r.getDrawable(R.drawable.ic_blue_launcher);   
layers[1] = r.getDrawable(R.drawable.ic_red_launcher);  
layers[2] = r.getDrawable(R.drawable.ic_green_launcher); 
LayerDrawable layerDrawable = new LayerDrawable(layers)  
((ImageView) findViewById(R.id.imageview)).setImageDrawable(layerDrawable); 

/*在java代碼中引用: */
((ImageView) findViewById(R.id.imageview)).setImageDrawable(getResources().getDrawable(R.drawable.layer_bcg) 

2.4、在xml中使用layer-list



    

這裡寫圖片描述

2.5、利用LayerDrawable實現圖片簡單合成

在Android平台中Bitmap的疊加處理可以通過Canvas逐層繪畫就可以了,而Drawable的疊加呢? 除了使用BitmapDrawable的getBitmap方法將Drawable轉換為Bitmap外,還有另一個方案——LayerDrawable。

Bitmap bm = BitmapFactory.decodeResource(getResources(),R.drawable.ic_red_launcher);    
Drawable[] array = new Drawable[3];    
 array[0] = new PaintDrawable(Color.BLACK); //黑色    
 array[1] = new PaintDrawable(Color.WHITE); //白色       
 array[2] = new BitmapDrawable(bm); //位圖資源            
LayerDrawable ld = new LayerDrawable(array); //參數為上面的Drawable數組    
ld.setLayerInset(1, 1, 1, 1, 1);  //第一個參數1代表數組的第二個元素,為白色    
ld.setLayerInset(2, 2, 2, 2, 2); //第一個參數2代表數組的第三個元素,為位圖資源    
mImageView.setImageDrawable(ld);

如以上代碼所示setLayerInset方法原型為public void setLayerInset (int index, int l, int t, int r, int b) 其中第一個參數為層的索引號,後面的四個參數分別為left、top、right和bottom。對於簡單的圖片合成我們可以將第一和第二層的PaintDrawable換成BitmapDrawable即可實現簡單的圖片合成。

3、ShapeDrawable(shape xml)

ShapeDrawable用於定義基本的幾何圖形(如矩形、圓形、線條等),其根節點是shape(shape可以指定android:shape=[“rectangle” | “oval” | “line” | “ring”]中的一種指定定義何種集合類型),shape裡可以定義cornersgradientpaddingsizesolidstroke等子節點。

3.1、在xml文件中實現ShapeDrawable



    
    
    
    
    
    
    
    
    
    
    

3.2、在xml中使用shape

這裡寫圖片描述

3.3、在代碼中構造ShapwDrawable

在代碼中構造ShapeDrawable對象,需要涉及到Shape系列。

 mImg= (ImageView) findViewById(R.id.demo_img);
 float[] outerRadii = {20, 20, 40, 40, 60, 60, 80, 80};//外矩形 左上、右上、右下、左下 圓角半徑
 //float[] outerRadii = {20, 20, 20, 20, 20, 20, 20, 20};//外矩形 左上、右上、右下、左下 圓角半徑
 RectF inset = new RectF(100, 100, 200, 200);//內矩形距外矩形,左上角x,y距離, 右下角x,y距離
 float[] innerRadii = {20, 20, 20, 20, 20, 20, 20, 20};//內矩形 圓角半徑
 RoundRectShape roundRectShape = new RoundRectShape(outerRadii, inset, innerRadii);
 //RoundRectShape roundRectShape = new RoundRectShape(outerRadii, null, innerRadii); //無內矩形
 ShapeDrawable drawable=new ShapeDrawable(roundRectShape);
 drawable.getPaint().setColor(Color.GREEN);
 drawable.getPaint().setAntiAlias(true);
 drawable.getPaint().setStyle(Paint.Style.STROKE);//描邊
 drawable.getPaint().setStrokeWidth(20);
 drawable.setIntrinsicWidth(200);
 drawable.setIntrinsicHeight(400);
 drawable.setPadding(new Rect(4, 4, 4, 4));
 //drawable.setShape(Shape s);
 mImg.setBackground(drawable);

4、ClipDrawable(clip xml)

ClipDrawable 代表從其他位圖上截取一個”圖片片段“,根節點是clip,沒有其他子節點,clip裡有幾個屬性節點:

android:drawable 指定要截取的源Drawable android:clipOrientation:截取的方向,水平或者垂直截取 android:gravity:截取時的對齊方式


ClipDrawable有一個重要的方法setLevel(int level)可以用於設置截取區域的大小,當level為0時截取區域為空,為10000時截取整張圖片。

4.1、ClipDrawable 一個簡單的應用

例子的效果是模擬圖片從中間慢慢向左右兩邊展開的效果(懶得去實現自動展開的效果了,就用了一個按鈕,點擊一次展開一點)

mImg = (ImageView) findViewById(R.id.demo_img);
//獲取圖片顯示的ClipDrawable對象
final ClipDrawable clipDrawable = (ClipDrawable) mImg.getDrawable();
final Handler handler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
       if (msg.what == 123) {
           //修改ClipDrawable的level值
           clipDrawable.setLevel(clipDrawable.getLevel() + 300);
       }
   }
};
 Timer timer = new Timer();
 timer.schedule(new StartTask(handler, clipDrawable, timer), 2000);
 Button btn = (Button) findViewById(R.id.plus_level);
 btn.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
         handler.sendEmptyMessage(123);
     }
 });
class StartTask extends TimerTask {
        private Handler handler;
        private Drawable drawable;
        private Timer timer;
        public StartTask(Handler handler, Drawable drawable, Timer timer) {
            super();
            this.handler = handler;
            this.drawable = drawable;
            this.timer = timer;
        }
        @Override
        public void run() {
            Message msg = new Message();
            msg.what = 123;
            handler.sendMessage(msg);
            if (drawable.getLevel() >= 10000) {
                timer.cancel();
            }
        }
    }

這裡寫圖片描述

5、AnimationDrawable

AnimationDrawable相信大家都不陌生,Android中AnimationDrawable支持兩種動畫:逐幀動畫(Frame)和補間動畫(Tween)。

5.1、逐幀動畫(animation-list xml)

根節點為animation-list,子節點為item,每一個item為一幀



    
    
    
    

在代碼中構造出AnimationDrawable對象,並設置到view的background上,然後設置開始播放就可以了:

AnimationDrawable ad = (AnimationDrawable)getResources().getDrawable(R.drawable.bootanimation);
mView.setBackgroundDrawable(ad);
ad.start();

5.2、補間動畫(set)

補間動畫則是以set作為根節點,set裡還可以定義4個子節點:

alpha: 設置圖片的透明度(0-1.0) scale:設置圖片進行大小變換 translate:設置圖片進行位移變換 rotate:設置圖片進行旋轉

5.2.1、定義補間動畫xml語法



    
    
    
    
    
        ...
    

5.2.2、在代碼中使用補間動畫

ImageView img = (ImageView) findViewById(R.id.tween_bcg);
Animation tweenAnimation = AnimationUtils.loadAnimation(this, R.anim.anim_tween);
img.startAnimation(tweenAnimation);

6、GradientDrawable

GradientDrawable就是漸變Drawable系,用一個例子來說明

package com.crazymo.drawableapp;
public class GradientActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new SampleView(this));
    }
    private static class SampleView extends View {
        private Path mPath;
        private Paint mPaint;
        private Rect mRect;
        private GradientDrawable mDrawable;

        public SampleView(Context context) {
            super(context);
            setFocusable(true);
            mPath = new Path();
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mRect = new Rect(0, 0, 120, 120);
            mDrawable = new GradientDrawable(GradientDrawable.Orientation.TL_BR,
                    new int[]{0xFFFF0000, 0xFF00FF00,
                            0xFF0000FF});
            mDrawable.setShape(GradientDrawable.RECTANGLE);
            mDrawable.setGradientRadius((float) (Math.sqrt(2) * 60));
        }

        static void setCornerRadii(GradientDrawable drawable, float r0,
                                   float r1, float r2, float r3) {
            drawable.setCornerRadii(new float[]{r0, r0, r1, r1,
                    r2, r2, r3, r3});
        }

        @Override
        protected void onDraw(Canvas canvas) {
            mDrawable.setBounds(mRect);
            float r = 16;
            canvas.save();
            canvas.translate(10, 10);
            mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);
            setCornerRadii(mDrawable, r, r, 0, 0);
            mDrawable.draw(canvas);
            canvas.restore();

            /*canvas.save();
            canvas.translate(10 + mRect.width() + 10, 10);
            mDrawable.setGradientType(GradientDrawable.RADIAL_GRADIENT);
            setCornerRadii(mDrawable, 0, 0, r, r);
            mDrawable.draw(canvas);
            canvas.restore();

            canvas.translate(0, mRect.height() + 10);

            canvas.save();
            canvas.translate(10, 10);
            mDrawable.setGradientType(GradientDrawable.SWEEP_GRADIENT);
            setCornerRadii(mDrawable, 0, r, r, 0);
            mDrawable.draw(canvas);
            canvas.restore();

            canvas.save();
            canvas.translate(10 + mRect.width() + 10, 10);
            mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);
            setCornerRadii(mDrawable, r, 0, 0, r);
            mDrawable.draw(canvas);
            canvas.restore();

            canvas.translate(0, mRect.height() + 10);

            canvas.save();
            canvas.translate(10, 10);
            mDrawable.setGradientType(GradientDrawable.RADIAL_GRADIENT);
            setCornerRadii(mDrawable, r, 0, r, 0);
            mDrawable.draw(canvas);
            canvas.restore();
            canvas.save();
            canvas.translate(10 + mRect.width() + 10, 10);
         mDrawable.setGradientType(GradientDrawable.SWEEP_GRADIENT);
            setCornerRadii(mDrawable, 0, r, 0, r);
            mDrawable.draw(canvas);
            canvas.restore();
*/
        }
    }
}

這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved