Android的各种Drawable讲解

news/2024/7/7 20:57:15

Android把可绘制的对象抽象为Drawable,不同的图形图像资源就代表着不同的drawable类型。Android FrameWork提供了一些具体的Drawable实现,通常在代码中都不会直接接触Drawable的实现类。
        在实际的开发过程中,会把使用到的资源都放置在res/drawable目录,剩下的工作交给Android SDK 就行了,当需要使用图片资源的时候,可以使用@drawable标志在xml中引用drawable资源就行,也可以在代码中使用id引用这些drawable资源。
        在使用drawable资源的时,有一点需要注意,drawable默认是内存共享的,也就说在不同的地方使用了同一个drawable,它们都指向相同的资源,而且具有相同的状态,如果在一个地方修改了这个drawable,所有使用它的地方都会改变。
        Android内置了如下几种Drawable类型:ColorDrawable、GradientDrawable、BitmapDrawable、 NinePatchDrawable、InsetDrawable、ClipDrawable、ScaleDrawable、RotateDrawable、AnimationDrawable、LayerDrawable、LevelListDrawable、StateListDrawable、TransitionDrawable。
        除了这些预置的drawable实现类以外,也可以自定义drawable的实现类型,大部分情况都不需要自定义drawable类型,使用系统提供的这些drawable实现类型已经覆盖了很多情况。在实际的编程过程中也很少会接触这些具体drawable实现类型,因为编写android应用程序使用xml可以很容易的创建drawable,只有在程序中需要修改drawable的属性时,才需要使用具体的drawable类型提供的方法来处理。下面就来逐个认识这些Drawable类型。

一、ColorDrawable

        ColorDrawable 是最简单的Drawable,它实际上是代表了单色可绘制区域,它包装了一种固定的颜色,当ColorDrawable被绘制到画布的时候会使用颜色填充Paint,在画布上绘制一块单色的区域。

        在xml文件中使用color作为根节点来创建ColorDrawable,它只有一个android:color属性,通过它来决定ColorDrawable的颜色,Android并没有提供修改这个颜色值的Api,所以这个颜色一旦设置之后,就不能直接修改了。

        下面的xml文件定义了一个颜色为红色的ColorDrawable:

[代码]xml代码:

1 <?xml version="1.0" encoding="utf-8"?>
2 <color xmlns:android="http://schemas.android.com/apk/res/android"
3  android:color="#FF0000" />
  
      当然也可以使用Java代码创建ColorDrawable,需要注意的是Android中使用一个int类型的数据表示颜色值,通常习惯使用十六进制格式的数据表示颜色值。一个int类型包含四个字节,分别代表颜色的4个组成部分:透明度(Alpha)、红(RED)、绿(GREEN)、蓝(BLUE),每个部分由一个字节(8个bit)表示,取值范围为0~255。在xml中使用颜色时可以省略透明度(Alpha)部分,如#ff0000表示红色。但是在代码中必须要明确指出透明度(Alpha)代表的数据,如果省略了就表示完全透明的颜色,例如0xFFFF0000表示红色,而0xFF0000虽然也表示红色,但它却是完全透明的,也就是说当绘制到画布上时,看不出有任何效果。

        使用Java代码也可以创建ColorDrawable,代码如下:

[代码]java代码:

1 ColorDrawable drawable = new ColorDrawable(0xffff0000);

二、GradientDrawable

        GradientDrawable 表示一个渐变区域,可以实现线性渐变、发散渐变和平铺渐变效果,在Android中可以使用GradientDrawable表示很多复杂而又绚丽的界面效果。

        可以使用xml定义GradientDrawable,相对于ColorDrawable类型,GradientDrawable要复杂很多,它有很多的元素组成。在xml文件中使用shape作为根节点来创建GradientDrawable,它包含很多属性和子节点,下面是GradientDrawable的xml文档节点结构。

[代码]xml代码:

1 <?xml version="1.0" encoding="utf-8"?>
2 <shape xmlns:android="http://schemas.android.com/apk/res/android">
3     <size /> //定义区域的大小
4     <gradient>//设置区域背景的渐变效果
5         <solid/>//设置区域的背景颜色,如果设置了solid会覆盖gradient的效果
6         <stroke />//设置区域的边框效果
7         <padding />//设置区域的内边距
8 </shape>

        其中每个节点都有许多属性需要设置,以达到不同的渐变效果。

        以下是几种不同渐变效果实现的xml文件代码:

[代码]xml代码:

01 <!-- 线性渐变效果的椭圆-->
02 <?xml version="1.0" encoding="utf-8"?>
03 <shape
04     xmlns:android="http://schemas.android.com/apk/res/android"
05 android:shape="oval">
06  
07     <gradient
08         android:startColor="#ff0000"
09         android:centerColor="#00ff00"
10         android:endColor="#0000ff"
11         android:angle="90" />
12     <stroke
13         android:width="3dip"
14         android:color="#fff"
15         android:dashWidth="4dip"
16         android:dashGap="5dip" />
17 </shape>
18  
19 <!-- 平铺渐变效果的圆环-->
20 <?xml version="1.0" encoding="utf-8"?>
21 <shape xmlns:android="http://schemas.android.com/apk/res/android"
22     android:shape="ring" android:innerRadiusRatio="8"
23     android:thicknessRatio="3" android:useLevel="false">
24     <gradient android:type="sweep" android:useLevel="false"
25         android:startColor="#ff0000" android:endColor="#0000ff"android:centerColor="#00ff00"/>
26 </shape>
27  
28 <!-- 发散渐变效果的圆-->
29 <?xml version="1.0" encoding="utf-8"?>
30 <shape xmlns:android="http://schemas.android.com/apk/res/android"
31     android:shape="ring" android:innerRadius="0dip"
32     android:thickness="70dip" android:useLevel="false">
33     <gradient android:type="radial" android:useLevel="false" android:gradientRadius="70"
34         android:startColor="#ff0000" android:endColor="#0000ff"android:centerColor="#00ff00"/>
35 </shape>

        以下几幅图展示了上述三个渐变效果:

图6-1  线性渐变效果的椭圆

图6-2  平铺渐变效果的圆环

图6-3  发散渐变效果的圆

三、BitmapDrawable

        BitmapDrawable 是对bitmap的一种包装,可以设置它包装的bitmap在BitmapDrawable区域内的绘制方式,如平铺填充、拉伸填充或者保持图片原始大小,也可以在BitmapDrawable区域内部使用gravity指定的对齐方式。

        在xml文件中使用bitmap作为根节点来定义BitmapDrawable。

        下面的xml代码定义一个BitmapDrawable,同时设置了BitmapDrawable的tileMode 属性为mirror,通过这样设置会使用小图片在水平和竖直方向做镜面平铺效果。

[代码]xml代码:

1 <?xml version="1.0" encoding="utf-8"?>
2 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
3     android:src="@drawable/png_icon_416"
4     android:tileMode="mirror"
5     android:antialias="true"
6     android:dither="true"
7     >
8 </bitmap>

        也可以使用Java代码实现相同的效果,等价的Java代码如下:

[代码]java代码:

1 Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.png_icon_416);
2 BitmapDrawable mBitmapDrawable = new BitmapDrawable(mBitmap);
3 mBitmapDrawable.setTileModeXY(TileMode.MIRROR, TileMode.MIRROR);
4 mBitmapDrawable.setAntiAlias(true);
5 mBitmapDrawable.setDither(true);
6 mDrawable = mBitmapDrawable;

        效果如下图所示:
 

图6-4  BitmapDrawable运行效果图

四、NinePatchDrawable

        NinePatchDrawable,“点九图”是Andriod平台的一种特殊的图片格式,文件扩展名为:.9.png。支持Android平台的手机类型很多,有多种不同的分辨率,很多控件的切图文件在被放大拉伸后,边角会模糊失真。在android平台下使用“点九”图片处理技术,可以将图片横向和纵向同时进行拉伸,以实现在多分辨率下的完美显示效果。点九图片在拉伸时仍能保留图像的渐变质感和圆角的精细度。

        Android SDK工具集提供了处理点九图片的工具,可以通过draw9patch.bat运行,通过这个工具可以很容易把普通的PNG图片处理成“点九”图片。从它的名字也很容易理解“点九”图的含义,其实相当于把一张PNG图分成了9个部分(九宫格),分别为4个角,4条边,以及一个中间区域,4个角是不做拉伸的,所以还能一直保持圆角的清晰状态,而2条水平边和2条垂直边分别只做水平和垂直拉伸,所以不会出现边框被拉粗的情况,只有中间用黑线指定的区域做拉伸,通过这种处理方式图片才不会失真。如图6-5所示,对4条黑线分别做了注释。左边和上边的黑线形成的矩形区域是图片的拉伸区域,下边和右边形成的矩形区域是内容所在的区域。黑线可以是连续的也可以是不连续的,不过为了达到最好的显示效果,最好使用连续的黑线。
 

图6-5  点九图片示意图

        使用了*.9.png图片技术后,只需要采用一套界面切图去适配不同的分辨率,而且大幅减少安装包的大小。Android FrameWork在显示点九图片时使用了高效的优化算法,所示应用程序不需要专门做处理就可以实现图片拉伸自适应,减少了代码量和实际开发的工作量。 

        在xml文件中使用使用nine-patch作为根节点创建NinePatchDrawable。同时,也可以使用bitmap包装点九图片,android FrameWork会根据android:src属性设置的图片类型来生成对应的drawable。代码如下:

[代码]xml代码:

1 <?xml version="1.0" encoding="utf-8"?>
2 <nine-patch
3     xmlns:android="http://schemas.android.com/apk/res/android"
4     android:src="@drawable/droid_logo"
5     android:dither="true" />

[代码]xml代码:

1 <?xml version="1.0" encoding="utf-8"?>
2 <bitamp
3     xmlns:android="http://schemas.android.com/apk/res/android"
4     android:src="@drawable/droid_logo"
5     android:dither="true" />

        下面看一下原始点九图片以及拉伸之后的效果:

图6-6  原始点九图片


图6-7  点九图片拉伸之后的效果

        最后,需要指出的是,Android虽然可以使用Java代码创建NinePatchDrawable,但是极少情况会那么做,主要的原因是由于Android SDK会在编译工程时对点九图片进行编译,形成特殊格式的图片。使用代码创建NinePatchDrawable时只能针对编译过的点九图片资源,对于没有编译过的点九图片资源都当做BitmapDrawable对待。在使用点九图片时需要注意的是,点九图只能适用于拉伸的情况,对于压缩的情况并不适用,如果需要适配很多分辨率的屏幕时需要把点九图做的小一点。

五、InsetDrawable

        InsetDrawable 表示一个drawable嵌入到另外一个drawable内部,并且在内部留一些间距,这一点很像drawable的padding属性,区别在于 padding表示drawable的内容与drawable本身的边距,insetDrawable表示两个drawable和容器之间的边距。当控件需要的背景比实际的边框小的时候比较适合使用InsetDrawable。

        在xml文件中使用inset作为跟节点定义InsetDrawable。

        下面的xml定义了一个四边边距都为20dip的InsetDrawable,代码如下:

[代码]xml代码:

1 <?xml version="1.0" encoding="utf-8"?>
2 <inset xmlns:android="http://schemas.android.com/apk/res/android"
3     android:drawable="@drawable/bitmap_bell"
4     android:insetLeft="20dp"
5     android:insetRight="20dp"
6     android:insetTop="20dp"
7     android:insetBottom="20dp"
8     >
9 </inset>

        效果如下图所示:
 

图6-8  InsetDrawable运行效果图

六、ClipDrawable

        ClipDrawable 是对一个Drawable进行剪切操作,可以控制这个drawable的剪切区域,以及相相对于容器的对齐方式,android中的进度条就是使用一个ClipDrawable实现效果的,它根据level的属性值,决定剪切区域的大小。

        在xml文件中使用clip作为根节点定义ClipDrawable。

        需要注意的是ClipDrawable是根据level的大小控制图片剪切操作的,官方文档的note中提到:The drawable is clipped completely and not visible when the level is 0 and fully revealed when the level is 10,000。也就是level的大小从0到10000,level为0时完全不显示,为10000时完全显示。是用Drawable提供的setLevel(int level)方法来设置剪切区域。

        下面为定义ClipDrawable的代码:

[代码]xml代码:

1 <?xml version="1.0" encoding="utf-8"?>
2 <clip xmlns:android="http://schemas.android.com/apk/res/android"
3     android:clipOrientation="horizontal"
4     android:drawable="@drawable/bitmap_android"
5     android:gravity="left"
6     >
7 </clip>

        如果没有android:drawable属性,必须要设置一个任意类型的drawable作为子节点,代码如下:

[代码]xml代码:

01 <?xml version="1.0" encoding="utf-8"?>
02 <clip xmlns:android="http://schemas.android.com/apk/res/android"
03     android:clipOrientation="horizontal"
04     android:gravity="left"
05     >
06     <bitmap
07         android:src="@drawable/android_text"
08         android:gravity="center"
09         />
10 </clip>

        效果如下图所示:
 

图6-9  ClipDrawable运行效果图

七、ScaleDrawable

        ScaleDrawable是对一个Drawable进行缩放操作,可以根据level属性控制这个drawable的缩放比率,也可以设置它在容器中的对齐方式。

        在xml文件中使用scale作为根节点来创建RotateDrawable。

        创建ScaleDrawable的代码如下:

1 <?xml version="1.0" encoding="utf-8"?>
2 <!-- android:scaleGravity=""可以设置缩放的对齐方式 -->
3 <scale xmlns:android="http://schemas.android.com/apk/res/android"
4     android:drawable="@drawable/smiley_smile"
5     android:scaleWidth="100%"
6     android:scaleHeight="100%"
7     >
8      
9 </scale>

        效果如下图所示:

QQ截图20120606150541.png


图6-10  ScaleDrawable运行效果图


八、 RotateDrawable

        RotateDrawable 是对一个Drawable进行旋转操作,可以根据level属性控制这个drawable旋转角度,也可以设置相对于它所在容器的对齐方式。

        在xml文件中使用rotate作为根节点来定义RotateDrawable.

        创建RotateDrawable的代码如下:

1 <?xml version="1.0" encoding="utf-8"?>
2 <rotate xmlns:android="http://schemas.android.com/apk/res/android"
3     android:drawable="@drawable/smiley_smile"
4     android:pivotX="50%"
5     android:pivotY="50%"
6     >
7      
8  
9 </rotate>

        效果如下图所示:

QQ截图20120606151807.png

图6-11  RotateDrawable运行效果图


九、AnimationDrawable

        AnimationDrawable 对应于Android中的帧动画,就是把一系列的drawable按照一定的顺序,一帧一帧的播放,并且可以使用android:oneshot属性设置是否循环播放。

        在xml文件中使用animation-list作为根节点定义AnimationDrawable,使用item设置需要播放的每一帧使用的drawable资源,以及每一帧持续的时常。

        下面的代码定义了一个包含五帧的AnimationDrawable,帧间隔为300毫秒,代码如下:

01 <?xml version="1.0" encoding="utf-8"?>
02 <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
03     android:oneshot="false">
04     <item
05         android:drawable="@drawable/level1"
06         android:duration="300"
07         />
08     <item
09         android:drawable="@drawable/level2"
10         android:duration="300"
11         />
12     <item
13         android:drawable="@drawable/level3"
14         android:duration="300"
15         />
16     <item
17         android:drawable="@drawable/level4"
18         android:duration="300"
19         />
20     <item
21         android:drawable="@drawable/level5"
22         android:duration="300"
23         />
24 </animation-list>

        定义了AnimationDrawable之后需要主动调用AnimationDrawable的start播放动画,需要注意的是,当我们在Activity的oncreate方法中调用start方法时会没有任何效果,那是因

        为view还没有初始化完成,无法播放动画,所以需要使用handler来延迟播放动画,具体实现代码如下:

1 mHandler.postDelayed(new Runnable() {
2          
3         @Override
4         public void run() {
5                 // TODO Auto-generated method stub
6                 ((AnimationDrawable)mDrawable).start();
7                  
8         }
9 }, 1000);

十、LayerDrawable

        LayerDrawable 管理一组drawable,每个drawable都处于不同的层,当它们被绘制的时候,按照顺序全部都绘制到画布上。虽然这些drawable会有交差或者重叠的区域,但是它们是位于不同的层,彼此之间不会影响。

        在xml文件中使用layer-list作为根节点来定义LayerDrawable,通过item子节点定义每一层的drawable,layer-list没有属性节点,只包含item子节点。

        下面的xml定义了一个包含三层的LayerDrawable,为了清楚的看到它们分别位于不同的层,可以给每一层都设置了一些透明度,代码如下:

1 <?xml version="1.0" encoding="utf-8"?>
2 <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
3     <item android:drawable="@drawable/layer1" />
4     <item android:drawable="@drawable/layer2" />
5     <item android:drawable="@drawable/layer3" />
6 </layer-list>

        效果如下图所示:

QQ截图20120606155548.png


图6-12  LayerDrawable运行效果图


十一、LevelListDrawable

        管理一组drawable,每一个drawable都对应一个level范围,当它们被绘制的时候,根据level属性值选取对应的一个drawable绘制到画布上。

        在xml文件中使用level-list作为根节点来定义LevelListDrawable,通过item子节点定义每一层的drawable,level-list没有属性节点,只包含item子节点。

        创建LevelListDrawable的代码如下:

01 <?xml version="1.0" encoding="utf-8"?>
02 <level-list xmlns:android="http://schemas.android.com/apk/res/android" >
03  
04     <item
05         android:maxLevel="2000"
06         android:drawable="@drawable/level1" />   
07     <item
08         android:maxLevel="4000"
09         android:drawable="@drawable/level2" />
10     <item
11         android:maxLevel="6000"
12         android:drawable="@drawable/level3" />
13     <item
14         android:maxLevel="8000"
15         android:drawable="@drawable/level4" />
16     <item
17         android:maxLevel="10000"
18         android:drawable="@drawable/level5" />
19  
20 </level-list>

        效果如下图所示:

QQ截图20120606161047.png


图6-13  LevelListDrawable运行效果图1

QQ截图20120606161055.png


图6-14  LevelListDrawable运行效果图2


十二、StateListDrawable

        StateListDrawable管理一组drawable,每一个drawable都对应着一组状态,状态的选择类似于java中的switch-case组合,按照顺序比较状态,当遇到匹配的状态后,就返回对应的drawable,因此需要把最精确的匹配放置在最前面,按照从精确到粗略的顺序排列。

        StateListDrawable在Android中使用的非常广泛,所有控件的背景基本上都使用了StateListDrawable,比如按钮就具有很多状态,按下状态、选中状态、默认状态、禁用状态等等,像这样在不用的状态下显示效果不一样的时候,就是需要使用StateListDrawable的时候。

        在xml文件中使用selector作为根节点来定义StateListDrawable,并使用item定义不同状态下的drawable。

        创建StateListDraw的代码如下:

01 <?xml version="1.0" encoding="utf-8"?>
02 <selector xmlns:android="http://schemas.android.com/apk/res/android" >
03     <item android:state_focused="false"
04         android:state_pressed="false"
05         android:drawable="@drawable/gradient_normal"
06         />
07      
08     <item android:state_pressed="true"
09         android:drawable="@drawable/gradient_pressed"
10         />
11      
12     <item android:state_focused="true"
13         android:drawable="@drawable/gradient_focused"
14         />
15  
16 </selector>

        效果如下图所示:

QQ截图20120606163955.png


图6-15  Normal状态下StateListDrawable运行效果图

QQ截图20120606164003.png


图6-16  Focused状态下StateListDrawable运行效果图

QQ截图20120606164009.png


图6-17  Pressed状态下StateListDrawable运行效果图


十三、TransitionDrawable

        TransitionDrawable 是LayerDrawable的子类,不过它只负责管理两层drawable,并且提供了一个透明度变化的动画,可以控制从一层drawable过度到另外一层drawable的动画效果。

        在xml文件中使用transition作为根节点来定义TransitionDrawable,通过item子节点定义两层使用的drawable。

        创建TransitionDrawable的代码如下:

1 <?xml version="1.0" encoding="utf-8"?>
2 <transition xmlns:android="http://schemas.android.com/apk/res/android" >
3     <item android:drawable="@drawable/smiley_smile"/>
4     <item android:drawable="@drawable/smiley_smile_glasses"/>
5  
6 </transition>

        在使用AnimationDrawable的时,需要主动调用startTransition方法启动两个层之间的切换动画,也可以调用reverseTransition方法启动逆向切换动画,它们都可以接受一个毫秒

数,作为动画的持续时间。代码如下:

1 mHandler.postDelayed(new Runnable() {
2          
3         @Override
4         public void run() {
5                 // TODO Auto-generated method stub
6                 ((TransitionDrawable)mDrawable).startTransition(2000);
7         }
8 }, 1000);

        效果如下图所示:

QQ截图20120606165324.png


图6-18  TransitionDrawable运行效果图1

QQ截图20120606165330.png


图6-19  TransitionDrawable运行效果图2




转载地址:http://yaoming168.iteye.com/blog/1633702






http://www.niftyadmin.cn/n/3649137.html

相关文章

使用黑盒测试在 Go 中重写 Bash 脚本

目录 前言&#xff1a; 开始 准备工作 描述行为&#xff1a;Bats 简介 行为描述&#xff1a;陷阱 描述行为&#xff1a;设计测试 重写&#xff1a;让我们开始用go吧&#xff01; 重构和更新&#xff1a;实现胜利 结论 前言&#xff1a; 使用黑盒测试在Go中重写Bash脚本…

Ormlite的工具使用

配置 compile com.j256.ormlite:ormlite-android:5.0 使用 常用注解 DatabaseTable(tableName "t_user") 指定实体和表的一一对应关系 DatabaseField() 指定属性与表中列的一一对应关系 常用配置说明&#xff1a; 主键&#xff1a;id true 自增主键&#xff1a;gen…

如何在Ubuntu 18.04上使用Ansible使用LAMP安装和设置WordPress

介绍 (Introduction) Server automation now plays an essential role in systems administration, due to the disposable nature of modern application environments. Configuration management tools such as Ansible are typically used to streamline the process of aut…

Windows文本框星号密码查看器

Windows文本框星号密码查看器本人2002的学习作品作者&#xff1a;成晓旭1、 设计原理&#xff1a;注册一个系统级鼠标挂钩&#xff0c;通过监测系统鼠标所在Windows窗口来获取密码&#xff0c;成功获取密码之后&#xff0c;通过发送自定义的Windows系统消息&#xff0c;到宿主…

Celery 链接RabbitMQ报错CRITICAL/MainProcess] Frequent restarts detected: RestartFreqExceeded('5 in 1s',)

为了别人&#xff0c;也是为了将来自己忘了&#xff0c;备忘一个问题 在实现Celery链接RabbitMQ的时候&#xff0c;感觉万事具备了&#xff0c;却报错&#xff1a; CRITICAL/MainProcess] Frequent restarts detected: RestartFreqExceeded(5 in 1s,) raceback (most recent ca…

简单使用style实现沉浸式状态栏

我之前也写过一个沉浸式的文章&#xff1a;http://blog.csdn.net/qq_24675479/article/details/78557698 今天写一个比较简单点的&#xff1a; 默认情况下的style&#xff1a; <resources><!-- Base application theme. --><style name"AppTheme" p…

ts构建koa_如何使用Koa构建“ Hello World”应用程序

ts构建koa介绍 (Introduction) Express is one of the most popular Node.js frameworks out there. Koa is a new web framework created by the team behind Express. It aims to be a modern and more minimalist version of Express. Some of its characteristics are its …

新旧身份证合法性验证及相互转换算法

新旧身份证合法性验证及相互转换算法——谨以此文献给共事3年即将离职的PPL作者&#xff1a;成晓旭前天&#xff0c;看到PPL在一个需要网站上注册&#xff0c;但该网站要求输入一个身份证号码&#xff0c;并且随便输入一个还不行&#xff1a;对方还要验证输入身份证的合法性&am…