首先Drawable是一个抽象类,表示的是可以在Canvas中绘制的图像,常被用作一个view的背景,有多种实现类完成不同的功能。其次Drawable大致可以分为这几类:图片、由颜色构成的图像。一般用xml中进行定义。
使用方法getIntrinsicWidth、getIntrinsicHeight来获取宽高
用于显示一张图片,如下示例
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android" android:antialias="true" android:dither="true" android:filter="true" android:gravity="top" android:src="@mipmap/girl" android:tileMode="repeat" />
android:antialias 是否开启抗锯齿
android:dither 是否开启防抖动
android:filter 是否开启过滤效果
android:gravity 用于对图片进行定位
android:src 图片资源id
android:tileMode 平铺模式,repeat、mirror、clamp三种
代表了单色可绘制区域,包装了一种固定的颜色,在画布上绘制一块单色的区域。
<?xml version="1.0" encoding="utf-8"?>
<color xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/colorAccent">
</color>
还可以用代码创建
ColorDrawable drawable = new ColorDrawable(int color); //传入一个color的integer值
即9-patch图,可以根据内容进行自由缩放宽高而不失真
<?xml version="1.0" encoding="utf-8"?>
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true" android:filter="true" android:src="@color/colorAccent">
</nine-patch>
图中1、2方向表示在draw9patch中绘制黑线,黑线长度交集为可拉伸的范围
图中3、4方向黑线长度交集表示内容可以填充的区域
通过颜色来构造图形,既可以为纯色图形,也可以为具有渐变效果的图形。能构成的图形有rectangle、oval、ring、line
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<gradient android:angle="45" android:centerColor="@color/colorAccent" android:centerX="50%" android:centerY="50%" android:endColor="@color/colorPrimary" android:gradientRadius="150dp" android:startColor="@color/colorPrimaryDark" android:type="sweep" />
<size android:width="260dp" android:height="260dp" />
</shape>
注意:1、android:angle值必须为45的倍数 2、oval用于绘制椭圆,当size的宽高相等时绘制成圆
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:innerRadius="100dp" android:shape="ring" android:thickness="10dp" android:useLevel="false" >
<stroke android:width="10dp" android:color="@color/colorAccent" />
</shape>
注意:
android:shape 要绘制的形状,rectangle、oval、ring、line
stroke 形状的描边,有如下属性
solid 纯色填充,android:color指定shape颜色
gradient 渐变效果,与solid不可一起用,有如下属性
corners 表示矩形(rectangle)的四个角的角度,不适用于其他shape ,有如下属性
size shape的宽高,对应着android:width、android:height
可以看作是一个状态选择器,通过view不同的状态选择对应的item中的drawable显示
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/colorPrimaryDark" android:state_pressed="false"></item>
<item android:drawable="@color/colorAccent" android:state_pressed="true"></item>
</selector>
android:state_pressed 当按住一个view时,按下的状态
android:state_checked 当一个view被选中时,适用于CheckBox
android:state_selected 当一个view被选择时
android:state_enabled 当一个view处于可用状态
android:state_focused 当view获取焦点
表示的是一种分层的的Drawable集合,类似于ps中的图层的概念,将多个drawable放在不同的层上面形成一种叠加的效果
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/night" />
<item android:drawable="@mipmap/photo6" android:gravity="center" />
</layer-list>
表示一个drawable集合,集合中的每一个Drawable都有一个等级(level),通过设置不同的等级,可以使LevelListDrawable切换至不同的Drawable。等级范围在0~10000之间, android:maxLevel设置最大level, android:minLevel设置最小level
示例:
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/photo0" android:maxLevel="20" android:minLevel="10" />
<item android:drawable="@mipmap/photo1" android:maxLevel="40" android:minLevel="30" />
</level-list>
通过设置level可以切换不同的Drawable,在代码中
//将ImageView的背景切换为photo1, 35 在30~40之间
iv.setImageLevel(35);
//将ImageView的背景切换为photo0, 15在10~20之间
iv.setImageLevel(15);
LayerDeawable的子类,用于实现连个Drawable的淡入淡出效果
示例:
xml文件定义
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/night" />
<item android:drawable="@mipmap/photo6" />
</transition>
给ImageView设置src,在java代码中
iv= (ImageView) findViewById(R.id.iv_transition);
drawable = (TransitionDrawable) iv.getDrawable();
drawable.startTransition(1000); // 实现淡入淡出效果
drawable.reverseTransition(1000);
嵌入其他Drawable,并可以在四周保留一定的间距
示例:
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@mipmap/photo6" android:inset="20dp">
</inset>
根据等级将一个Drawable缩放到一定的比例,当level为0时不可见,当level为10000时无缩放效果
示例:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@mipmap/night" android:scaleGravity="center" android:scaleHeight="50%" android:scaleWidth="50%" />
要显示出效果,必须设置level大于0
iv = (ImageView) findViewById(R.id.iv_scale);
ScaleDrawable drawable= (ScaleDrawable) iv.getDrawable();
drawable.setLevel(1);
- android:scaleHeight="percentage",android:scaleWidth="percentage",设置宽高缩放为原来的比例为(100%-percentage)
- 设置level越大,图像显示越大
根据自己的等级(level)来对另一个Drawable进行裁剪,裁剪的方向由android:clipOrientation、android:gravity共同决定。设置level进行裁剪,level的大小从0到10000,level为0时完全不显示,为10000时完全显示
xml定义
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="horizontal" android:drawable="@mipmap/night" android:gravity="right"></clip>
设置给ImageView
<ImageView android:id="@+id/iv_clip" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/drawable_clip" />
通过设置level来裁剪
ImageView iv = (ImageView) findViewById(R.id.iv_clip);
ClipDrawable drawable= (ClipDrawable) iv.getDrawable();
drawable.setLevel(5000); // 设置的level越大裁剪的范围越小
android:clipOrientation ,horizontal 水平方向裁剪,vertical 垂直方向裁剪
android:gravity ,配合裁剪方向
package com.yu.drawablelearing;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
public class CircleDrawable extends Drawable{
private int radius;
private int mWidth;
private int mHeight;
private Paint mPaint;
@Override
public void draw(Canvas canvas) {
canvas.drawCircle(mWidth/2,mHeight/2,radius,mPaint);
}
public CircleDrawable(Bitmap bitmap) {
radius = Math.min(bitmap.getWidth(), bitmap.getHeight())/2;
mWidth = bitmap.getWidth();
mHeight = bitmap.getHeight();
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setShader(bitmapShader);
mPaint.setAntiAlias(true);
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
invalidateSelf();
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public int getIntrinsicHeight() {
return mHeight;
}
@Override
public int getIntrinsicWidth() {
return mWidth;
}
}
package com.yu.drawablelearing;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
/** * Created by pecu on 2016/08/24. */
public class RoundRectangleDrawable extends Drawable {
private RectF rectF;
private Paint mPaint;
Bitmap mBitmap;
@Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(rectF, mBitmap.getWidth()/6,mBitmap.getHeight()/6, mPaint);
}
public RoundRectangleDrawable(Bitmap bitmap) {
mBitmap = bitmap;
mPaint = new Paint();
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setAntiAlias(true);
mPaint.setShader(bitmapShader);
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
invalidateSelf();
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
rectF = new RectF(left, top, right, bottom);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public int getIntrinsicWidth() {
return mBitmap.getWidth();
}
@Override
public int getIntrinsicHeight() {
return mBitmap.getHeight();
}
}