android的Drawable详解

Drawable简介

Drawable有很多种,用来表示一种图像的概念,但他们又不完全是图像,他们是用过颜色构建出来的各种图像的表现形式。Drawable一般都是通过xml来定义的 ,当然我们也可以通过代码来创建,Drawable是一个抽象的类,是所以Drawable的基类,每个具体的Drawable都是它的子类,如ShapeDrawable,BitmapDrwable等,其结构如下图:

Drawable的内部有两个重要的参数需要说明,getIntrinsicHeight 和 getIntrinsicWidth,通过他们可以获取内部图片的高度和宽度,但是并不是所以的Drawable都有内部宽和高,比如一个颜色形成的Drawable就没有内部宽和高。

Drawable分类

Drawable种类繁多,比如,BitmapDrawable,ShapeDrwable,LayerDrawable,StateListDrawable等,这里就不一一列举了,下面列出一些常用的做一下简单的介绍。

ColorDrawable

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

在xml文件中使用color作为根节点来创建ColorDrawable,它只有一个android:color属性,通过它来决定ColorDrawable的颜色.

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

当然,我们也可以通过代码来创建,不过需要注意的是习惯使用十六进制格式的数据表示颜色值。

ColorDrawable drawable = new ColorDrawable(0xffff0000);

GradientDrawable

gradientDrawable表示一个渐变区域,可以实现线性渐变、发散渐变和平铺渐变效果,在Android中可以使用GradientDrawable表示很多复杂而又绚丽的界面效果。在xml文件中使用shape作为根节点来创建GradientDrawable,它包含很多属性和子节点,下面是GradientDrawable的xml文档节点结构。

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

BitmapDrawable

bitmapDrawable是对bitmap的一种包装,它表示的就是一张图片,我们可以通过xml方式来描述它。我们可以使用不同的属性含义来绘制他,如Android:src,android.dither等。

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

当然我们用代码也是可以实现的。

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

NinePatchDrawable

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

使用了*.9.png图片技术后,只需要采用一套界面切图去适配不同的分辨率,而且大幅减少安装包的大小。

对于创建ninePatchDrawable也是极其简单的。

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

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

clipDrawable听名字就是对Drawable进行裁剪的。android中的进度条就是使用一个ClipDrawable实现效果的,它根据level的属性值,决定剪切区域的大小。

需要注意的是ClipDrawable是根据level的大小控制图片剪切操作的,level大小从0到10000。

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

需要注意的是如果没有android:drawable属性,必须要设置一个任意类型的drawable作为子节点。

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:gravity="left"
    >
    <bitmap
        android:src="@drawable/android_text"
        android:gravity="center"
        />
</clip>

AnimationDrawable
animationDrawable就是动画的,这个是按帧播放的那种。使用起来也非常简单,在xml文件中使用animation-list作为根节点定义AnimationDrawable,使用item设置需要播放的每一帧使用的drawable资源,以及每一帧持续的时间即可。

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item
        android:drawable="@drawable/level1"
        android:duration="300"
        />
    <item
        android:drawable="@drawable/level2"
        android:duration="300"
        />
    <item
        android:drawable="@drawable/level3"
        android:duration="300"
        />
    <item
        android:drawable="@drawable/level4"
        android:duration="300"
        />
    <item
        android:drawable="@drawable/level5"
        android:duration="300"
        />
</animation-list>

 代码实现,定义了AnimationDrawable之后需要主动调用AnimationDrawable的start播放动画,需要注意的是,当我们在Activity的oncreate方法中调用start方法时会没有任何效果,那是因为view还没有完成初始化,所以正确的使用方法是。

mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
                // TODO Auto-generated method stub
                ((AnimationDrawable)mDrawable).start();
        }
}, 1000);

LayerDrawable
layerDrawable顾名思义就是处于不同的层的,管理一组drawable,每个drawable都处于不同的层,当它们被绘制的时候,按照顺序全部都绘制到画布上。虽然有时候可能出现交错的情况,但是由于位于不同的层,显示上 也是不会有任何影响的。

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

LevelListDrawable

levelDrawable的每一个drawable都对应一个level范围,当它们被绘制的时候,根据level属性值选取对应的一个drawable绘制到画布上。就像波浪线一样。

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:maxLevel="2000"
        android:drawable="@drawable/level1" />
    <item
        android:maxLevel="4000"
        android:drawable="@drawable/level2" />
    <item
        android:maxLevel="6000"
        android:drawable="@drawable/level3" />
</level-list>

StateListDrawable
stateListDrawable管理一组drawable,每一个drawable都对应着一组状态,状态的选择类似于java中的switch-case组合,按照顺序比较状态,当遇到匹配的状态后,就返回对应的drawable,因此需要把最精确的匹配放置在最前面,按照从精确到粗略的顺序排列。这也是我们开发中用的最多的,写背景选择器的时候,我们一般只会使用两种状态,其实它可以表示很多种状态,几乎可以实现很多效果。

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

其实还有些Drawable,这里就不一一讲解了。

时间: 2024-10-30 05:14:20

android的Drawable详解的相关文章

【Android 基础】详解Animation 动画介绍和实现_Android

在前面 PopupWindow 实现显示仿腾讯新闻底部弹出菜单有用到Animation动画效果来实现菜单的显示和隐藏,本文就来介绍下吧. 1.Animation 动画类型 Android的animation由四种类型组成: XML中 alph 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果 JavaCode中 AlphaAnimation 渐变透明度动画效果 ScaleAnimation 渐变尺寸伸缩动画效果

android 之断点续传详解三部曲之[二] → 断点续传下载

在上一篇中,我们简单介绍了如何创建多任务下载,但那种还不能拿来实用,这一集我们重点通过代码为大家展示如何创建多线程断点续传下载,这在实际项目中很常用. 和上一篇中一样,先来布局文件: main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" and

Android Dialog对话框详解_Android

废话不多说了,直接给大家贴代码了. 布局文件xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_paren

android 通知Notification详解及实例代码

android Notification实例详解 1.使用Builder模式来创建 2.必须要设置一个smallIcon,还可以设置setTicker 3.可以设置 setContentTitle,setContentInfo,setContentText,setWhen 4.可以设置setDefaults(闪屏,声音,震动),通过Notification设置flags(能不能被清除) 5.发送需要获取一个NotificationManager(getSystemService来获取);noti

Android 中Seekbar详解及简单实例

Android 中Seekbar详解及简单实例 做到音频播放和音乐播放时,大多数都要用到Seekbar.现在我先简单介绍下Seekbar的几个重要属性. android:max 设置值的大小 . android:thumb="@drawable/" 显示的那个可拖动图标,如果没有设置该参数则为系统默认,如果自己需要重新定义,则将自己需要的图标存放在资源目录 /res/drawable下,然后调用即可. android:thumbOffset 拖动图标的偏量值,可以让拖动图标超过bar的

Android Animation动画详解(二): 组合动画特效

前言     上一篇博客Android Animation动画详解(一): 补间动画 我已经为大家介绍了Android补间动画的四种形式,相信读过该博客的兄弟们一起都了解了.如果你还不了解,那点链接过去研读一番,然后再过来跟着我一起学习如何把简单的动画效果组合在一起,做出比较酷炫的动画特效吧. 一. 动画的续播     如题,大家想想,如果一个页面上包含了许多动画,这些动画要求按顺序播放,即一个动画播放完成后,继续播放另一个动画,使得这些动画具有连贯性.那该如何实现呢? 有开发经验或者是逻辑思维

android网络应用开发详解

Android网络应用开发,主要有两种方式,一种是socket(是对tcp/udp协议的封装),另外一种就是使用Http协议,Android中主要提供了两种方式,HttpURLConnection和Apache HttpClient.下面对Android网络应用开发进行具体的阐述. 一.基于socket的网络通信 socket是为了网络服务提供的一种机制.通信的两端都是socket. 网络通信其实就是socket间的通信. 数据在两个socket间进行io传输. 1.基于udp的socket编程

Android系统service详解

Android存在3大类service, 处于android系统的不同框架层,具体解读如下: 1) init.rc中的service //关键词"service"  name  二进制可执行程序路径 service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart healthd onrestart restart zygote

Android 混淆代码详解及实例

  Android 混淆代码详解及实例         为了防止自己的劳动成果被别人窃取,混淆代码能有效防止被反编译,下面来总结以下混淆代码的步骤: 1. 大家也许都注意到新建一个工程会看到项目下边有这样proguard-project.txt一个文件,这个对混淆代码很重要,如果你不小心删掉了,没关系,从其他地方拷贝一个过来 2. 最重要的就是在proguard-project.txt添加混淆的申明了: a. 把所有你的jar包都申明进来,例如: -libraryjars libs/apns_1