概述
2D绘图
通常情况下,我们很少直接使用Drawable的实现类,大部分的情况下还是使用xml的方式进行开发。只有在程序中需要动态的修改drawable的属性时,才需要使用具体的drawable类型提供的方法。
事实上xml中配置的节点和Drawable的实现类是一一对应的。
Android 在android.graphics.drawable包中提供了了很多Drawable抽象类的实现类:ColorDrawable、GradientDrawable、BitmapDrawable、 NinePatchDrawable、InsetDrawable、ClipDrawable、ScaleDrawable、RotateDrawable、AnimationDrawable、LayerDrawable、LevelListDrawable、StateListDrawable、TransitionDrawable等等
Element | Class | Description |
---|---|---|
AnimatedRotateDrawable | A Drawable that can animate a rotation of another Drawable. | |
AnimationDrawable | An object used to create frame-by-frame animations, defined by a series of Drawable objects, which can be used as a View object’s background. | |
BitmapDrawable | A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. | |
ClipDrawable | A Drawable that clips another Drawable based on this Drawable’s current level value. You can control how much the child Drawable gets clipped in width and height based on the level, as well as a gravity to control where it is placed in its overall container. Most often used to implement things like progress bars. | |
ColorDrawable | A specialized Drawable that fills the Canvas with a specified color, with respect to the clip region. | |
InsetDrawable | A Drawable that insets another Drawable by a specified distance. This is used when a View needs a background that is smaller than the View’s actual bounds. | |
LayerDrawable | A Drawable that manages an array of other Drawables. These are drawn in array order. | |
LevelListDrawable | A resource that manages a number of alternate Drawables, each assigned a maximum numerical value. | |
NinePatchDrawable | A resizeable bitmap, with stretchable areas that you define. | |
RotateDrawable | A Drawable that can rotate another Drawable based on the current level value. The start and end angles of rotation can be controlled to map any circular arc to the level values range. | |
ScaleDrawable | A Drawable that changes the size of another Drawable based on its current level value. | |
StateListDrawable | Lets you assign a number of graphic images to a single Drawable and swap out the visible item based on state. | |
GradientDrawable | Basic method for drawing shapes via XML. | |
TransitionDrawable | An extension of that is intended to cross-fade between the first and second layer. The format is exactly the same as . |
http://idunnolol.com/android/drawables.html
ColorDrawable
ColorDrawable 实际上是代表了单色可绘制区域,它包装了一种固定的颜色,当ColorDrawable被绘制到画布的时候会使用颜色填充Paint,在画布上绘制一块单色的区域。
Xml的方式
android:background=”@drawable/colordrawable_xml”
代码语言:javascript复制 "@ id/id_tv_colorDrawableDemo_Xml"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="ColorDrawable-ByXml"
android:textColor="@color/bg_black"
android:background="@drawable/colordrawable_xml"
android:textSize="20sp" />
颜色定义在color.xml中,使用时直接引用即可。
代码语言:javascript复制<color xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/skyblue"/>
JavaCode的方式
代码中必须要明确指出透明度(Alpha)代表的数据,即,要加上0x,而且不能把透明度漏掉,否则就是透明的了。
代码语言:javascript复制public class ColorDrawableActivity extends AppCompatActivity {
private TextView mIdTvColorDrawableDemo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_color_drawable);
mIdTvColorDrawableDemo = (TextView) findViewById(R.id.id_tv_colorDrawableDemo_javaCode);
/**
* setBackground 在 4.1(API16)之后增加
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
/**
* 使用Java代码创建ColorDrawable,
* 需要注意的是Android中使用一个int类型的数据表示颜色值,
* 通常习惯使用十六进制格式的数据表示颜色值。
* 一个int类型包含四个字节,
* 分别代表颜色的4个组成部分:透明度(Alpha)、红(RED)、绿(GREEN)、蓝(BLUE),
* 每个部分由一个字节(8个bit)表示,取值范围为0~255。
* 在xml中使用颜色时可以省略透明度(Alpha)部分,
* 如#ff0000表示红色。
* 但是在代码中必须要明确指出透明度(Alpha)代表的数据,
* 如果省略了就表示完全透明的颜色,也就是说当绘制到画布上时,看不出有任何效果。
*/
mIdTvColorDrawableDemo.setBackground(new ColorDrawable(0xffff0000));
}
}
}
运行图
GradientDrawable
GradientDrawable 表示一个渐变区域,可以实现线性渐变、发散渐变和平铺渐变效果。
在xml文件中使用shape作为根节点来创建GradientDrawable,很多属性和子节点。
shape
Xml的方式
线性渐变linear
代码语言:javascript复制<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<gradient
android:angle="90"
android:centerColor="#00ff00"
android:endColor="#0000ff"
android:startColor="#ff0000" />
<stroke
android:width="3dip"
android:color="#fff"
android:dashGap="5dip"
android:dashWidth="4dip" />
shape>
发散渐变radial
代码语言:javascript复制<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thickness="100dp"
android:useLevel="false">
<gradient
android:centerColor="#FFEB82"
android:endColor="#35B2DE"
android:gradientRadius="50"
android:startColor="#DEACAB"
android:type="radial"
android:useLevel="false" />
shape>
平铺渐变sweep
代码语言:javascript复制<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadiusRatio="8"
android:shape="ring"
android:thicknessRatio="3"
android:useLevel="false">
<gradient
android:centerColor="#FFEB82"
android:endColor="#35B2DE"
android:startColor="#DEACAB"
android:type="sweep"
android:useLevel="false" />
shape>
引用的Activity
代码语言:javascript复制<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@ id/id_tv_gradientDrawableDemo_Xml1"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:layout_margin="10dp"
android:background="@drawable/gradient_linear"
android:gravity="center"
android:text="线性渐变linear-ByXml"
android:textColor="@color/bg_black"
android:textSize="20sp" />
<TextView
android:id="@ id/id_tv_gradientDrawableDemo_Xml2"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:layout_margin="10dp"
android:background="@drawable/gradient_radial"
android:gravity="center"
android:text="发散渐变radial-ByXml"
android:textColor="@color/bg_black"
android:textSize="20sp" />
<TextView
android:id="@ id/id_tv_gradientDrawableDemo_Xml3"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:layout_margin="10dp"
android:background="@drawable/gradient_sweep"
android:gravity="center"
android:text="平铺渐变sweep-ByXml"
android:textColor="@color/bg_black"
android:textSize="20sp" />
LinearLayout>
运行图
BitmapDrawable
BitmapDrawable 是对bitmap的一种包装,可以设置它包装的bitmap在BitmapDrawable区域内的绘制方式,如平铺填充、拉伸填充或者保持图片原始大小,也可以在BitmapDrawable区域内部使用gravity指定的对齐方式。
在xml文件中使用bitmap作为根节点来定义BitmapDrawable。
可选属性说明:
- src:图片资源~ antialias:是否支持抗锯齿 filter:是否支持位图过滤,支持的话可以是图批判显示时比较光滑
- dither:是否对位图进行抖动处理
- gravity:若位图比容器小,可以设置位图在容器中的相对位置
- tileMode:指定图片平铺填充容器的模式,设置这个的话,gravity属性会被忽略,有以下可选值: disabled(整个图案拉伸平铺),clamp(原图大小), repeat(平铺),mirror(镜像平铺)
Xml的方式
代码语言:javascript复制<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:src="@drawable/ic_launcher"
android:tileMode="mirror" />
JavaCode的方式
代码语言:javascript复制import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import com.turing.base.R;
import com.turing.base.utils.AlertUtil;
public class BitmapDrawableActivity extends AppCompatActivity {
private ImageView mIdBitmapDrawableXml;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bitmap_drawable);
mIdBitmapDrawableXml = (ImageView) findViewById(R.id.id_bitmapDrawable_xml);
// 通过代码的方式创建BitmapDrawable
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.zjl);
BitmapDrawable mBitmapDrawable = new BitmapDrawable(mBitmap);
mBitmapDrawable.setTileModeXY(Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
mBitmapDrawable.setAntiAlias(true);
mBitmapDrawable.setDither(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mIdBitmapDrawableXml.setBackground(mBitmapDrawable);
// mIdBitmapDrawableXml.setImageDrawable(mBitmapDrawable);
} else {
AlertUtil.showDialogWithClose(this, "API<16 不支持setBackground属性设置");
}
}
}
这种方式基本上很啰嗦,很少会用到,了解下就好了
运行图
InsetDrawable
表示把一个Drawable嵌入到另外一个Drawable的内部,并且在内部留一些间距, 类似与Drawable的padding属性,但padding表示的是Drawable的内容与Drawable本身的边距! 而InsetDrawable表示的是两个Drawable与容器之间的边距,*当控件需要的背景比实际的边框 小的时候,比较适合使用InsetDrawable*
比如使用这个可以解决我们自定义Dialog与屏幕之间 的一个间距问题,相信做过的朋友都知道,即使我们设置了layout_margin的话也是没用的,这个 时候就可以用到这个InsetDrawable了!只需为InsetDrawable设置一个insetXxx设置不同 方向的边距,然后为设置为Dialog的背景即可!
相关属性如下:
- drawable:引用的Drawable,如果为空,必须有一个Drawable类型的子节点!
- visible:设置Drawable是否可见
- insetLeft,insetRight,insetTop,insetBottm:设置左右上下的边距
Xml的方式
代码语言:javascript复制<RelativeLayout 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_parent"
tools:context="com.turing.base.activity.drawable.InsetDrawableActivity">
<ImageView
android:id="@ id/mIv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="@drawable/zjl"
android:src="@drawable/insetdrawable_simple" />
RelativeLayout>
insetdrawable_simple.xml
代码语言:javascript复制<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetBottom="60dp"
android:insetLeft="30dp"
android:insetRight="30dp"
android:insetTop="60dp"
android:visible="true">
<shape android:shape="rectangle">
<solid android:color="#0000ff" />
shape>
inset>
JavaCode的方式
代码语言:javascript复制public class InsetDrawableActivity extends AppCompatActivity {
private ImageView mMIv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inset_drawable);
mMIv = (ImageView) findViewById(R.id.mIv);
// JavaCode
InsetDrawable insetDrawable = new InsetDrawable(getResources()
.getDrawable(R.drawable.zjl), 30, 60, 30, 60);
// 设置
mMIv.setImageDrawable(insetDrawable);
}
}
NinePathDrawable
如何制作.9图片
在AS中使用.9图需要注意:
- .9图片必须放在drawable目录下,不能存放在mipmap下
- AS中的.9图,必须要有黑线,不然编译都不会通过
使用“点九”图片处理技术,可以将图片横向和纵向同时进行拉伸,以实现在多分辨率下的完美显示效果。点九图片在拉伸时仍能保留图像的渐变质感和圆角的精细度。
Android SDK工具集提供了处理点九图片的工具,可以通过draw9patch.bat运行,通过这个工具可以很容易把普通的PNG图片处理成“点九”图片。
从它的名字也很容易理解“点九”图的含义,其实相当于把一张PNG图分成了9个部分(九宫格),分别为4个角,4条边,以及一个中间区域,4个角是不做拉伸的,所以还能一直保持圆角的清晰状态,而2条水平边和2条垂直边分别只做水平和垂直拉伸,所以不会出现边框被拉粗的情况,只有中间用黑线指定的区域做拉伸,通过这种处理方式图片才不会失真。如图6-5所示,对4条黑线分别做了注释。左边和上边的黑线形成的矩形区域是图片的拉伸区域,下边和右边形成的矩形区域是内容所在的区域。黑线可以是连续的也可以是不连续的,不过为了达到最好的显示效果,最好使用连续的黑线。
使用了*.9.png图片技术后,只需要采用一套界面切图去适配不同的分辨率,而且大幅减少安装包的大小。
要点: 左上拉伸 右下内容
在xml文件中使用使用nine-patch作为根节点创建NinePatchDrawable。同时,也可以使用bitmap包装点九图片,android FrameWork会根据android:src属性设置的图片类型来生成对应的drawable。
不过这样使用基本也是太啰嗦了,直接设置背景图就可以了,这里只是说明下可以这样使用~
xml定义NinePatchDrawable:
代码语言:javascript复制<nine-patch
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/dule_pic"
android:dither="true"/>
使用Bitmap包装.9图片:
代码语言:javascript复制<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/dule_pic"
android:dither="true"/>
最后,需要指出的是,Android虽然可以使用Java代码创建NinePatchDrawable,但是极少情况会那么做,主要的原因是由于Android SDK会在编译工程时对点九图片进行编译,形成特殊格式的图片。使用代码创建NinePatchDrawable时只能针对编译过的点九图片资源,对于没有编译过的点九图片资源都当做BitmapDrawable对待。在使用点九图片时需要注意的是,点九图只能适用于拉伸的情况,对于压缩的情况并不适用,如果需要适配很多分辨率的屏幕时需要把点九图做的小一点。
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)方法来设置剪切区域。
- clipOrietntion:设置剪切的方向,可以设置水平和竖直2个方向
- gravity:从那个位置开始裁剪
- drawable:引用的drawable资源,为空的话需要有一个Drawable类型的子节点 . 如果没有android:drawable属性,必须要设置一个任意类型的drawable作为子节点
<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>
核心:通过代码修改ClipDrawable的level的值!Level的值是0~10000!
Code
在主布局文件中设置一个ImageView,将src设置为clipDrawable! 记住是src,如果你写成了blackground的话会报空指针
activity_clip_drawable_actvity.xml
代码语言:javascript复制<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@ id/id_iv_clipdrawable"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/clipdrawable_xml"/>
LinearLayout>
clipdrawable_xml.xml
代码语言:javascript复制<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="horizontal"
android:drawable="@drawable/zjl"
android:gravity="left"/>
第一种方式 推荐
代码语言:javascript复制public class ClipDrawableActvity extends AppCompatActivity {
private ImageView mIdIvClipdrawable;
private ClipDrawable clipDrawable;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 0x110) {
// level 增加
clipDrawable.setLevel(clipDrawable.getLevel() 500);
Message message = Message.obtain();
message.what = 0x110;
handler.sendMessageDelayed(message, 500);
if (clipDrawable.getLevel() > 10000) {
handler.removeMessages(0x110);
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clip_drawable_actvity);
mIdIvClipdrawable = (ImageView) findViewById(R.id.id_iv_clipdrawable);
clipDrawable = (ClipDrawable) mIdIvClipdrawable.getDrawable();
handler.sendEmptyMessage(0x110);
}
}
第二种方式:
代码语言:javascript复制public class ClipDrawableActvity extends AppCompatActivity {
private ImageView mIdIvClipdrawable;
private ClipDrawable clipDrawable;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 0x110) {
// level 增加
clipDrawable.setLevel(clipDrawable.getLevel() 500);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clip_drawable_actvity);
mIdIvClipdrawable = (ImageView) findViewById(R.id.id_iv_clipdrawable);
clipDrawable = (ClipDrawable) mIdIvClipdrawable.getDrawable();
// 开启定时任务
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(0x110);
// 到达最大值后,取消任务
if (clipDrawable.getLevel() > 10000) {
timer.cancel();
}
}
}, 0, 500);
}
}
运行图
ScaleDrawable
ScaleDrawable是对一个Drawable进行缩放操作,可以根据level属性控制这个drawable的缩放比率,也可以设置它在容器中的对齐方式。
在xml文件中使用scale作为根节点来创建RotateDrawable。
- android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签
- android:scaleHeight 设置可缩放的高度,用百分比表示,格式为XX%, 0%表示不做任何缩放,50%表示只能缩放一半
- android:scaleWidth 设置可缩放的宽度,用百分比表示,格式为XX%, 0%表示不做任何缩放,50%表示只能缩放一半
- android:scaleGravity 设置drawable缩放后的位置,取值和bitmap标签的一样,默认值是left
http://stackoverflow.com/questions/5507539/android-scaledrawable-doesnt-seems-to-work
首先声明一下,通过xml的方式 无效了。。。。。。
Code
代码语言:javascript复制 <ImageView
android:id="@ id/id_show_scaleDrawable"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/scaledrawable_simple"/>
scaledrawable_simple.xml
代码语言:javascript复制<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/face"
android:scaleGravity="center"
android:scaleHeight="100%"
android:scaleWidth="100%" />
sorry,这样行不通了。 我们用代码的方式来创建吧
代码语言:javascript复制public class ScaleDrawableActivity extends AppCompatActivity {
private ImageView mIdShowScaleDrawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scale_drawable);
mIdShowScaleDrawable = (ImageView) findViewById(R.id.id_show_scaleDrawable);
Resources res = getResources();
BitmapDrawable bd = (BitmapDrawable) res.getDrawable(R.drawable.zjl);
Bitmap b = Bitmap.createScaledBitmap(bd.getBitmap(),
(int) (bd.getIntrinsicHeight() * 0.7),
(int) (bd.getIntrinsicWidth() * 0.7),
false);
mIdShowScaleDrawable.setImageBitmap(b);
}
}
代码语言:javascript复制<RelativeLayout 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_parent"
tools:context="com.turing.base.activity.drawable.ScaleDrawableActivity">
<ImageView
android:id="@ id/id_show_scaleDrawable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
RelativeLayout>
RotateDrawable
RotateDrawable 是对一个Drawable进行旋转操作,可以根据level属性控制这个drawable旋转角度,也可以设置相对于它所在容器的对齐方式。
用来对Drawable进行旋转,也是通过setLevel来控制旋转的,最大值也是:10000
在xml文件中使用rotate作为根节点来定义RotateDrawable.
- fromDegrees:起始的角度,,对应最低的level值,默认为0
- toDegrees:结束角度,对应最高的level值,默认360
- pivotX:设置参照点的x坐标,取值为0~1,默认是50%,即0.5
- pivotY:设置参照点的Y坐标,取值为0~1,默认是50%,即0.5 ps:如果出现旋转图片显示不完全的话可以修改上述两个值解决!
- drawable:设置位图资源
- visible:设置drawable是否可见!
Code
代码语言:javascript复制<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/zjl"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="180"/>
AnimationDrawbale
详见本人另外博客 AnimationDrawable类:帧动画类
AnimationDrawable 对应于Android中的帧动画,就是把一系列的drawable按照一定的顺序,一帧一帧的播放,并且可以使用android:oneshot属性设置是否循环播放。
在xml文件中使用animation-list作为根节点定义AnimationDrawable,使用item设置需要播放的每一帧使用的drawable资源,以及每一帧持续的时常。
代码语言:javascript复制<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item
android:drawable="@drawable/horse1"
android:duration="100" />
<item
android:drawable="@drawable/horse2"
android:duration="100" />
<item
android:drawable="@drawable/horse3"
android:duration="100" />
<item
android:drawable="@drawable/horse4"
android:duration="100" />
<item
android:drawable="@drawable/horse5"
android:duration="100" />
<item
android:drawable="@drawable/horse6"
android:duration="100" />
<item
android:drawable="@drawable/horse7"
android:duration="100" />
<item
android:drawable="@drawable/horse8"
android:duration="100" />
animation-list>
定义了AnimationDrawable之后需要主动调用AnimationDrawable的start播放动画,需要注意的是,当我们在Activity的oncreate方法中调用start方法时会没有任何效果,那是因为view还没有初始化完成,无法播放动画,所以需要使用handler来延迟播放动画,具体实现代码如下:
代码语言:javascript复制mHandler.postDelayed(new Runnable() {
@Override
public void run() {
((AnimationDrawable)mDrawable).start();
}
}, 1000);
LayerDrawable
LayerDrawable 管理一组drawable,每个drawable都处于不同的层,当它们被绘制的时候,按照顺序全部都绘制到画布上。虽然这些drawable会有交差或者重叠的区域,但是它们是位于不同的层,彼此之间不会影响。
在xml文件中使用layer-list作为根节点来定义LayerDrawable,通过item子节点定义每一层的drawable,layer-list没有属性节点,只包含item子节点。
- drawable:引用的位图资源,如果为空徐璈有一个Drawable类型的子节点
- left:层相对于容器的左边距
- right:层相对于容器的右边距
- top:层相对于容器的上边距
- bottom:层相对于容器的下边距
- id:层的id
Code
下面我们通过一个自定义的Seekbar来演示下如何使用:
代码语言:javascript复制<RelativeLayout 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_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.turing.base.activity.drawable.LayerDrawableActivity">
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal"
android:indeterminateOnly="false"
android:maxHeight="10dp"
android:minHeight="5dp"
android:progressDrawable="@drawable/layerxml"
android:thumb="@drawable/shape_slider"
/>
RelativeLayout>
layerxml.xml
代码语言:javascript复制<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<corners android:radius="50dp" />
<solid android:color="#C2C2C1" />
shape>
item>
<item>
<clip>
<shape>
<corners android:radius="50dp" />
<solid android:color="#BCDA73" />
shape>
clip>
item>
layer-list>
shape_slider.xml
代码语言:javascript复制<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#2C96ED"/>
<size android:height="30dp" android:width="30dp"/>
shape>
主Activity
代码语言:javascript复制public class LayerDrawableActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layer_drawable);
}
}
运行图
LevelListDrawable
管理一组drawable,每一个drawable都对应一个level范围,当它们被绘制的时候,根据level属性值选取对应的一个drawable绘制到画布上。
在xml文件中使用level-list作为根节点来定义LevelListDrawable,通过item子节点定义每一层的drawable,level-list没有属性节点,只包含item子节点。
item可供设置的属性如下:
- drawable:引用的位图资源,如果为空需要有一个Drawable类型的子节点
- minlevel:level对应的最小值
- maxlevel:level对应的最大值
通过shapeDrawable画圆,一式五份,改下宽高即可:
代码语言:javascript复制<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#2C96ED"/>
<size android:height="20dp" android:width="20dp"/>
shape>
接着到LevelListDrawable,这里我们设置五层:
代码语言:javascript复制<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_circle1" android:maxLevel="2000"/>
<item android:drawable="@drawable/shape_circle2" android:maxLevel="4000"/>
<item android:drawable="@drawable/shape_circle3" android:maxLevel="6000"/>
<item android:drawable="@drawable/shape_circle4" android:maxLevel="8000"/>
<item android:drawable="@drawable/shape_circle5" android:maxLevel="10000"/>
level-list>
引用
android:src 一定要是src ,不能使background,否则会抛出空指针异常。
代码语言:javascript复制<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@ id/id_iv_levellist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/levellist" />
RelativeLayout>
代码语言:javascript复制import android.graphics.drawable.LevelListDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import com.turing.base.R;
public class LevelListDrawableActivity extends AppCompatActivity {
private ImageView imageView;
private LevelListDrawable levelListDrawable;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0x110:
if (levelListDrawable.getLevel() > 10000) {
// 设置为0 ,循环展示
levelListDrawable.setLevel(0);
imageView.setImageLevel(0);
//移除消息
// handler.removeMessages(0x110);
}
imageView.setImageLevel(levelListDrawable.getLevel() 2000);
Message message = Message.obtain();
message.what = 0x110;
handler.sendMessageDelayed(message, 500);
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_level_list_drawable);
imageView = (ImageView) findViewById(R.id.id_iv_levellist);
levelListDrawable = (LevelListDrawable) imageView.getDrawable();
imageView.setImageLevel(0);
handler.sendEmptyMessage(0x110);
}
}
StateListDrawable
StateListDrawable管理一组drawable,每一个drawable都对应着一组状态,状态的选择类似于java中的switch-case组合,按照顺序比较状态,当遇到匹配的状态后,就返回对应的drawable,因此需要把最精确的匹配放置在最前面,按照从精确到粗略的顺序排列。
StateListDrawable在Android中使用的非常广泛,所有控件的背景基本上都使用了StateListDrawable,比如按钮就具有很多状态,按下状态、选中状态、默认状态、禁用状态等等,像这样在不用的状态下显示效果不一样的时候,就是需要使用StateListDrawable的时候。
在xml文件中使用selector作为根节点来定义StateListDrawable,并使用item定义不同状态下的drawable。
代码语言:javascript复制<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_btn_lost_window_focused" android:state_window_focused="false" />
<item android:drawable="@drawable/bg_btn_disable" android:state_enabled="false" />
<item android:drawable="@drawable/bg_btn_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/bg_btn_selected" android:state_selected="true" />
<item android:drawable="@drawable/bg_btn_activated" android:state_activated="true" />
<item android:drawable="@drawable/bg_btn_normal" />
selector>
TransitionDrawable
TransitionDrawable 是LayerDrawable的子类,不过它只负责管理两层drawable,并且提供了一个透明度变化的动画,可以控制从一层drawable过度到另外一层drawable的动画效果。
在xml文件中使用transition作为根节点来定义TransitionDrawable,通过item子节点定义两层使用的drawable
优秀的文章1
优秀的文章2