Android各种Drawable讲解和demo实例

转载自  :

https://blog.csdn.net/linghu_java/article/details/42119969

PS:文字内容基本搬自所转载的博客,但是所有代码和图片均为博主实践而来,不过,归根结底,还是用的别人的轮子,所以还是归为转载。

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">

  4. </color>

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

二、GradientDrawable

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

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

在我们实际操作shape的时候我们需要先了解shape的各种属性的作用:

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <shape

  3. xmlns:android="http://schemas.android.com/apk/res/android"

  4. android:shape=["rectangle" | "oval" | "line" | "ring"] //共有4种类型,矩形(默认)/椭圆形/直线形/环形

  5. // 以下4个属性只有当类型为环形时才有效

  6. android:innerRadius="dimension" //内环半径

  7. android:innerRadiusRatio="float" //内环半径相对于环的宽度的比例,比如环的宽度为50,比例为2.5,那么内环半径为20

  8. android:thickness="dimension" //环的厚度

  9. android:thicknessRatio="float" //环的厚度相对于环的宽度的比例

  10. android:useLevel="boolean"> //如果当做是LevelListDrawable使用时值为true,否则为false.

  11. <corners //定义圆角

  12. android:radius="dimension" //全部的圆角半径

  13. android:topLeftRadius="dimension" //左上角的圆角半径

  14. android:topRightRadius="dimension" //右上角的圆角半径

  15. android:bottomLeftRadius="dimension" //左下角的圆角半径

  16. android:bottomRightRadius="dimension" /> //右下角的圆角半径

  17. <gradient //定义渐变效果

  18. android:type=["linear" | "radial" | "sweep"] //共有3中渐变类型,线性渐变(默认)/放射渐变/扫描式渐变

  19. android:angle="integer" //渐变角度,必须为45的倍数,0为从左到右,90为从上到下

  20. android:centerX="float" //渐变中心X的相当位置,范围为0~1

  21. android:centerY="float" //渐变中心Y的相当位置,范围为0~1

  22. android:startColor="color" //渐变开始点的颜色

  23. android:centerColor="color" //渐变中间点的颜色,在开始与结束点之间

  24. android:endColor="color" //渐变结束点的颜色

  25. android:gradientRadius="float" //渐变的半径,只有当渐变类型为radial时才能使用

  26. android:useLevel=["true" | "false"] /> //使用LevelListDrawable时就要设置为true。设为false时才有渐变效果

  27. <padding //内部边距

  28. android:left="dimension"

  29. android:top="dimension"

  30. android:right="dimension"

  31. android:bottom="dimension" />

  32. <size //自定义的图形大小

  33. android:width="dimension"

  34. android:height="dimension" />

  35. <solid //内部填充颜色

  36. android:color="color" />

  37. <stroke //描边

  38. android:width="dimension" //描边的宽度

  39. android:color="color" //描边的颜色

  40. // 以下两个属性设置虚线

  41. android:dashWidth="dimension" //虚线的宽度,值为0时是实线

  42. android:dashGap="dimension" /> //虚线的间隔

  43. </shape>

好了现在我们可以继续操作了:

我们只需要在主XML布局中定义如下:

 
  1. <LinearLayout

  2. android:orientation="vertical"

  3. android:layout_width="match_parent"

  4. android:layout_height="match_parent">

  5. <Button

  6. android:id="@+id/bt_testBtn"

  7. android:layout_width="match_parent"

  8. android:layout_height="match_parent"

  9. android:textSize="22sp"

  10. android:text="TestBtn"

  11. android:background="@drawable/bitmap_demo"

  12. />

  13. </LinearLayout>

之后效果的实现,都只需要更改android:background=""这一栏即可

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

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <!--线性椭圆渐变-->

  3. <shape xmlns:android="http://schemas.android.com/apk/res/android"

  4. android:shape="oval"

  5. >

  6. <gradient

  7. android:startColor="#ff0000"

  8. android:centerColor="#00ff00"

  9. android:endColor="#0000ff"

  10. android:angle="90"

  11. />

  12. <stroke

  13. android:color="#fff"

  14. android:width="3dp"

  15. android:dashWidth="4dp"

  16. android:dashGap="5dp"

  17. />

  18. </shape>

以下是几种不同渐变效果实现的xml文件代码和示例图

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <!--平铺渐变的椭圆-->

  3. <shape xmlns:android="http://schemas.android.com/apk/res/android"

  4. android:shape="ring"

  5. android:innerRadiusRatio="8"

  6. android:thicknessRatio="5"

  7. android:useLevel="false"

  8. >

  9. <gradient

  10. android:type="linear"

  11. android:useLevel="false"

  12. android:startColor="#ff0000"

  13. android:centerColor="#00ff00"

  14. android:endColor="#0000ff"

  15. />

  16. </shape>

以下是几种不同渐变效果实现的xml文件代码和示例图

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <!--发散渐变效果的圆-->

  3. <shape xmlns:android="http://schemas.android.com/apk/res/android"

  4. android:shape="ring"

  5. android:innerRadius="0dp"

  6. android:thickness="70dp"

  7. android:useLevel="false"

  8. >

  9. <gradient

  10. android:type="radial"

  11. android:useLevel="false"

  12. android:gradientRadius="70"

  13. android:startColor="#ff0000"

  14. android:centerColor="#00ff00"

  15. android:endColor="#0000ff"

  16. />

  17. </shape>

三、BitmapDrawable

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

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

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

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <bitmap xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:src="@drawable/ic_launcher"

  4. android:tileMode="mirror"

  5. android:antialias="true"

  6. android:dither="true">

  7. </bitmap>

这里出现图片平铺的原因是因为设置了

下面在实现nine-patch drawable 对比的时候,还会显示去掉该平铺字段的效果。

四、NinePatchDrawable

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

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

我们对默认的ic_launcher做9 patch处理,处理后结果如下:图片名为:ic_9pathch.9.png

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/ic_9patch"

  5. android:dither="true"

  6. />

最终效果:

如果不用nine-patch处理,就用原本ic_launcher的代码和效果如下:

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <bitmap xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:src="@drawable/ic_launcher"

  4. >

  5. </bitmap>

这也是不使用平铺效果的bitmap-drawable效果图

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

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

五、InsetDrawable

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

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

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

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <inset xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:drawable="@drawable/no_ninepatch_demo"

  4. android:inset="50dp"

  5. >

  6. </inset>

上面代码中no_ninepatch_demo就是上面不使用平铺效果图的drawable。

最终结果如下:

我们可以较之前,现在有了一定的边距。

六、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)方法来设置剪切区域。

好吧:发现被自己坑了,这里需要对之前的整个代码进行修改:

主xml  button改为imageview

 
  1. <LinearLayout

  2. android:orientation="vertical"

  3. android:layout_width="match_parent"

  4. android:layout_height="match_parent">

  5. <ImageView

  6. android:id="@+id/iv_testIv"

  7. android:layout_width="match_parent"

  8. android:layout_height="match_parent"

  9. android:textSize="22sp"

  10. android:src="@drawable/clip_demo"

  11. />

  12. </LinearLayout>

MainActivity也需要进行操作:

 
  1. private ImageView iv_testIv ;

  2. @Override

  3. protected void onCreate(@Nullable Bundle savedInstanceState) {

  4. super.onCreate(savedInstanceState);

  5. setContentView(R.layout.activity_main);

  6. iv_testIv = (ImageView) findViewById(R.id.iv_testIv);

  7. //获取图片所显示的ClipDrawble对象

  8. final ClipDrawable drawable = (ClipDrawable) iv_testIv.getDrawable();

  9. final Handler handler = new Handler() {

  10. public void handleMessage(Message msg) {

  11. if (msg.what == 0x1233) {

  12. //修改ClipDrawable的level值

  13. if (drawable != null)

  14. drawable.setLevel(drawable.getLevel() + 200);

  15. }

  16. }

  17. };

  18. final Timer timer = new Timer();

  19. timer.schedule(new TimerTask() {

  20. public void run() {

  21. Message msg = new Message();

  22. msg.what = 0x1233;

  23. //发送消息,通知应用修改ClipDrawable对象的level值

  24. handler.sendMessage(msg);

  25. //取消定时器

  26. if (drawable!=null)

  27. if (drawable.getLevel() >= 10000) {

  28. timer.cancel();

  29. }

  30. }

  31. }, 0, 30);

  32. }

最终结果为:

七、ScaleDrawable

ScaleDrawable是对一个Drawable进行缩放操作,可以根据level属性控制这个drawable的缩放比率,也可以设置它在容器中的对齐方式。
        在xml文件中使用scale作为根节点来创建RotateDrawable。
        创建ScaleDrawable的代码如下:

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <scale xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:drawable="@drawable/ic_launcher"

  4. android:scaleHeight="100%"

  5. android:scaleWidth="100%"

  6. >

  7. </scale>

然后还需要修改MainActivity,在上一步的基础上:

 
  1. //获取图片所显示的ClipDrawble对象

  2. // final ClipDrawable drawable = (ClipDrawable) iv_testIv.getDrawable();

  3. //获取图片的ScaleDrawable

  4. final ScaleDrawable drawable = (ScaleDrawable) iv_testIv.getDrawable() ;

改动这两行就可以了。

最后效果:

八、 RotateDrawable

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

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

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <rotate xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:drawable="@drawable/ic_launcher"

  4. android:pivotX="50%"

  5. android:pivotY="50%"

  6. android:fromDegrees="0"

  7. android:toDegrees="360"

  8. >

  9. </rotate>

经过上面上个实例,相信大家都知道了,现在还需要修改MainActivity中的drawable

 
  1. //获取图片所显示的ClipDrawble对象

  2. //final ClipDrawable drawable = (ClipDrawable) iv_testIv.getDrawable();

  3. //获取图片的ScaleDrawable

  4. //final ScaleDrawable drawable = (ScaleDrawable) iv_testIv.getDrawable() ;

  5. //获取图片的RotateDrawable

  6. final RotateDrawable drawable = (RotateDrawable) iv_testIv.getDrawable() ;

最终效果:

九、AnimationDrawable

AnimationDrawable 对应于Android中的帧动画,就是把一系列的drawable按照一定的顺序,一帧一帧的播放,并且可以使用android:oneshot属性设置是否循环播放。
        在xml文件中使用animation-list作为根节点定义AnimationDrawable,使用item设置需要播放的每一帧使用的drawable资源,以及每一帧持续的时常。
        下面的代码定义了一个包含五帧的AnimationDrawable,帧间隔为300毫秒,代码如下

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <animation-list xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:oneshot="false"

  4. >

  5. <item

  6. android:drawable="@drawable/ic_sentiment_dissatisfied_black_24dp"

  7. android:duration="300"

  8. />

  9. <item

  10. android:drawable="@drawable/ic_sentiment_neutral_black_24dp"

  11. android:duration="300"

  12. />

  13. <item

  14. android:drawable="@drawable/ic_sentiment_satisfied_black_24dp"

  15. android:duration="300"

  16. />

  17. <item

  18. android:drawable="@drawable/ic_sentiment_very_dissatisfied_black_24dp"

  19. android:duration="300"

  20. />

  21. </animation-list>

同样的我们还需要去修改MainActivity中的drawable相关代码,另外AnimationDrawable还需要手动启动

 
  1. //获取图片所显示的ClipDrawble对象

  2. //final ClipDrawable drawable = (ClipDrawable) iv_testIv.getDrawable();

  3. //获取图片的ScaleDrawable

  4. //final ScaleDrawable drawable = (ScaleDrawable) iv_testIv.getDrawable() ;

  5. //获取图片的RotateDrawable

  6. //final RotateDrawable drawable = (RotateDrawable) iv_testIv.getDrawable() ;

  7. //获取图片的AnimationDrawable

  8. final AnimationDrawable drawable = (AnimationDrawable) iv_testIv.getDrawable() ;

我们再去修改之后handle中的代码,添加一个start启动AnimationDrawable

 
  1. final Handler handler = new Handler() {

  2. public void handleMessage(Message msg) {

  3. if (msg.what == 0x1233) {

  4. //修改Drawable的level值

  5. if (drawable != null)

  6. {

  7. drawable.start();

  8. drawable.setLevel(drawable.getLevel() + 200);

  9. }

  10. }

  11. }

  12. };

PS:AnimationDrawable中level没有用了,但是保留也不会显示错误

最终效果:

十、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

  4. android:drawable="@drawable/ic_sentiment_very_dissatisfied_black_24dp"

  5. />

  6. <item

  7. android:drawable="@drawable/ic_sentiment_satisfied_black_24dp"/>

  8. <item

  9. android:drawable="@drawable/ic_sentiment_neutral_black_24dp"/>

  10. </layer-list>

最后,我们先去MainActivity中注释掉所有drawable相关的代码段。

然后运行得到:

可以发现,这是上面drawable中几张图的叠加。

十一、LevelListDrawable

管理一组drawable,每一个drawable都对应一个level范围,当它们被绘制的时候,根据level属性值选取对应的一个drawable绘制到画布上。
        在xml文件中使用level-list作为根节点来定义LevelListDrawable,通过item子节点定义每一层的drawable,level-list没有属性节点,只包含item子节点。

XML代码如下:

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <level-list xmlns:android="http://schemas.android.com/apk/res/android">

  3. <item

  4. android:drawable="@drawable/ic_sentiment_neutral_black_24dp"

  5. android:maxLevel="2000"

  6. />

  7. <item

  8. android:drawable="@drawable/ic_sentiment_satisfied_black_24dp"

  9. android:maxLevel="4000"

  10. />

  11. <item

  12. android:drawable="@drawable/ic_sentiment_very_dissatisfied_black_24dp"

  13. android:maxLevel="6000"

  14. />

  15. <item

  16. android:drawable="@drawable/ic_sentiment_dissatisfied_black_24dp"

  17. android:maxLevel="10000"

  18. />

  19. </level-list>

由于LevelListDrawable也是根据level来显示不同的item项目。所以我们需要去ManActivity中修改代码

 
  1. public class MainActivity extends AppCompatActivity {

  2. private static final String TAG = "MainActivity";

  3. private ImageView iv_testIv ;

  4. @Override

  5. protected void onCreate(@Nullable Bundle savedInstanceState) {

  6. super.onCreate(savedInstanceState);

  7. setContentView(R.layout.activity_main);

  8. iv_testIv = (ImageView) findViewById(R.id.iv_testIv);

  9. //获取图片所显示的ClipDrawble对象

  10. //final ClipDrawable drawable = (ClipDrawable) iv_testIv.getDrawable();

  11. //获取图片的ScaleDrawable

  12. //final ScaleDrawable drawable = (ScaleDrawable) iv_testIv.getDrawable() ;

  13. //获取图片的RotateDrawable

  14. //final RotateDrawable drawable = (RotateDrawable) iv_testIv.getDrawable() ;

  15. //获取图片的AnimationDrawable

  16. //final AnimationDrawable drawable = (AnimationDrawable) iv_testIv.getDrawable() ;

  17. final LevelListDrawable drawable = (LevelListDrawable) iv_testIv.getDrawable() ;

  18. final Handler handler = new Handler() {

  19. public void handleMessage(Message msg) {

  20. if (msg.what == 0x1233) {

  21. //修改Drawable的level值

  22. if (drawable != null)

  23. {

  24. // drawable.start();

  25. drawable.setLevel(drawable.getLevel() + 200);

  26. }

  27. }

  28. }

  29. };

  30. final Timer timer = new Timer();

  31. timer.schedule(new TimerTask() {

  32. public void run() {

  33. Message msg = new Message();

  34. msg.what = 0x1233;

  35. //发送消息,通知应用修改ClipDrawable对象的level值

  36. handler.sendMessage(msg);

  37. //取消定时器

  38. if (drawable!=null)

  39. if (drawable.getLevel() >= 10000) {

  40. drawable.setLevel(0) ;

  41. //timer.cancel();

  42. }

  43. }

  44. }, 0, 30);

  45. }

  46. }

最终运行的结果为:

十二、StateListDrawable

StateListDrawable管理一组drawable,每一个drawable都对应着一组状态,状态的选择类似于java中的switch-case组合,按照顺序比较状态,当遇到匹配的状态后,就返回对应的drawable,因此需要把最精确的匹配放置在最前面,按照从精确到粗略的顺序排列。
        StateListDrawable在Android中使用的非常广泛,所有控件的背景基本上都使用了StateListDrawable,比如按钮就具有很多状态,按下状态、选中状态、默认状态、禁用状态等等,像这样在不用的状态下显示效果不一样的时候,就是需要使用StateListDrawable的时候。
        在xml文件中使用selector作为根节点来定义StateListDrawable,并使用item定义不同状态下的drawable。定义如下XML:

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">

  3. <item

  4. android:state_pressed="false"

  5. android:drawable="@color/red"

  6. />

  7. <item

  8. android:state_pressed="true"

  9. android:drawable="@color/green"

  10. />

  11. </selector>

我们需要修改主xml文件,因为默认情况ImageView没有点击的功能,我们添加一个Button,为button绑定该drawable。代码很简单,就不再写出。

最终效果:

默认情况:

点击Button

十三、TransitionDrawable

TransitionDrawable 是LayerDrawable的子类,不过它只负责管理两层drawable,并且提供了一个透明度变化的动画,可以控制从一层drawable过度到另外一层drawable的动画效果。
        在xml文件中使用transition作为根节点来定义TransitionDrawable,通过item子节点定义两层使用的drawable。

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <transition xmlns:android="http://schemas.android.com/apk/res/android">

  3. <item android:drawable="@drawable/ic_sentiment_dissatisfied_black_24dp"/>

  4. <item android:drawable="@drawable/ic_sentiment_very_dissatisfied_black_24dp"/>

  5. </transition>

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

因此我们需要在MainActivity中去获取相关的TranstionDrawable对象和设置startTranstion

代码如下:

 final TransitionDrawable drawable = (TransitionDrawable) iv_testIv.getDrawable() ;
       drawable.startTransition(2000);

最终效果:

最后给上项目的github地址,

https://github.com/547291213/DecompilingActivity/tree/master

Android 系统(207)---Android各种Drawable讲解和demo实例相关推荐

  1. Android系统架构-[Android取经之路]

    摘要:本节主要来讲解Android的系统架构 阅读本文大约需要花费10分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! 欢 ...

  2. android 服务端技术,移动应用服务器端开发(基于JSP技术)-2017 Android系统构架 Android系统构架.docx...

    Android系统构架 PAGE 1 目 录 TOC \o "1-3" \h \z \u 一.Android系统构架 1 二.Linux内核层 2 三.系统运行库层 3 (一)系统 ...

  3. 【android系统】android系统升级流程分析(二)---update升级包分析

    接下来我们将通过几篇文章来分析update.zip包在具体Android系统升级的过程,来理解Android系统中Recovery模式服务的工作原理.今天让我先来分析下升级包update.zip. 一 ...

  4. 【android系统】android系统升级流程分析(一)---recovery模式中进行update包升级流程分析

    今天我们直接来看下android中具体的升级过程是如何的. 升级流程概述 升级的流程图: 升级流程分析 第一步:升级包获取 升级获取可以通过远程下载,也可直接拷贝到指定目录即可. 第二步:准备升级 然 ...

  5. android log抓取方法,Android系统之Android抓取各种log的方法

    Android系统之Android抓取各种log的方法 2018年11月25日 | 萬仟网移动技术 | 我要评论 android之android抓取各种log的方法 1.logcat (四类log b ...

  6. Android系统 (190)---Android:JSON 简介 amp; 解析方式 讲解(Gson、AS自带org.json、Jackson)

    Android:JSON 简介 & 解析方式 讲解(Gson.AS自带org.json.Jackson) 前言 现今最主流的数据交换格式 非 JSON莫属 今天,我将全面介绍 JSON &am ...

  7. android系统语音合成,android 语音合成报错

    发现了2个问题 第一个貌似是复制离线的资源出错了(已经核对过读写等权限): 12-19 19:54:49.739 32006-32159/com.zhanglf.youxuanz I/NonBlock ...

  8. Android系统(62)-----Android 7.1 新特性之 Shortcuts 介绍

    Android 7.1 新特性之 Shortcuts 介绍 Android 7.1 允许 App 自定义 Shortcuts,类似 iOS 的 3D touch.通过在桌面长按 App 弹出 Shor ...

  9. android系统弹窗,Android桌面弹窗实现总结

    在应用内弹出dialog其实很简单,但是在桌面上显示dialog却是有一些区别,大概思路有两个: --第一种是弹出一个真正的dialog,但是这是系统级的dialog,需要在manifest中获得系统 ...

最新文章

  1. deeplearning模型库
  2. webserver获取http请求方的服务器ip_光大科技基础设施团队剖析HTTP协议
  3. angr学习笔记(7)(malloc地址单元符号化)
  4. click传值vue_对vue下点击事件传参和不传参的区别详解
  5. childNodes在IE与Firefox中的区别
  6. Python之路:初识
  7. mysql5.7安装教程centos_CentOS7下MySQL5.7安装配置方法图文教程(YUM)
  8. 11月14日filter与在web开发中集成spring培训日记
  9. 应用Matlab小波变换工具箱进行图像压缩
  10. TopoDOT | 高精地图三维矢量元素提取——道路车道标线
  11. RuntimeError:The size of tensor a (100) must match the size of tensor b (12800) at non-singleton di
  12. 观察containerd-shim-runc-v2进程与容器里的1号进程
  13. Spring Security系列(一)——登录认证基本配置
  14. 第十二章 项目采购管理第六版
  15. activemq如何保证消息按顺序消费
  16. 家庭“好用”优化师:每一件好物都是在积攒生活闪光
  17. matlab对摄像头实时运动目标检测,基于Matlab实时运动目标跟踪检测系统
  18. 手撸SSO单点登录(五)登录验证-OA系统页面刷新或者跳转新OA系统页面
  19. 【深度学习图像识别课程】毕业项目:狗狗种类识别(3)代码实现
  20. 与外国教授用email交流

热门文章

  1. Sysfs_linux设备底层模型
  2. [计算机网络] - HTTP、HTTPS
  3. centos没有可用软件包 mysql-server_centos7解决yum install mysql-server没有可用包?
  4. linux mutex 数量上限,互斥量mutex
  5. Windows家庭版远程服务
  6. Java面试之什么是GCRoots,能做什么?
  7. Serializable序列化
  8. Web前端-Vue.js必备框架(一)
  9. 在eclipse上搭建springBoot
  10. 【Codeforces Round #438 C】 Qualification Rounds