前言
Android 中图片的显示基本都是基于Bitmap 和 Drawable 去绘制的.本文主要介绍其区别和作用
Bitmap是什么?
Bitmap是用于存储位图像素信息的数据.
Drawable 是什么?
-
一种可以在Canvas上进行绘制的抽象的概念
-
颜色、图片等都可以是一个Drawable
-
Drawable可以通过XML定义,或者通过代码创建
-
Android中Drawable是一个抽象类,每个具体的Drawable都是其子类
Bitmap 和Drawable的转换
-
Bitmap 转为Drawable对象
Bitmap转为Drawable对象是很简单的,将Bitmap作为参数传入,创见一个BitmapDrawable对象即可,BitmapDrawable集成了Drawable对象
public static Drawable bitMapToDrawable(Resources resource, Bitmap bitmap) {
return new BitmapDrawable(resource,bitmap);
}
以上是java代码,如果是kotlin,kotlin库中已经扩展了对应转换方法
bitmap.toDrawable(this.context.getResouces())
- Drawable 转 Bitmap
Drawable 转Bitmap 对象的代码稍显复杂.
java 版本
public static Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap = null;
if ( drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable)drawable;
if(bitmapDrawable.getBitmap() != null) return bitmapDrawable.getBitmap();
}
if( drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
// drawable 中高度 宽度存在问题时,返回一个像素大小的图
bitmap = Bitmap.createBitmap(1,1,Bitmap.Config.ARGB_8888);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight(),Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0,0,canvas.getWidth(),canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
kotlin 版本
drawable.toBitmap(20,20,Bitmap.Config.ARGB_8888)//前两个参数用于设置宽高
Drawable 如何自定义
在Android SDK已经有了绝大多数的Drawable实现类,比如 ColorDrawable等,但是有时侯还是需要自定义的,比如画一个图表.自定义Drawable 的一个重要作用是可以作为自定义View的一个绘制模块,相当对View更加灵活.当多个View都要绘制某个图时,可以搬到一个Drawable中.下面看看如何自定义一个Drawable.
class DrawableTestView(context:Context, attributeSet: AttributeSet):View(context,attributeSet) {
val pieDrawable = PieDrawable(values = arrayOf(100f,200f,300f), colors = arrayOf(Color.RED,Color.YELLOW,Color.GREEN))
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 绘制Drawable之前必须设置 bounds
pieDrawable.setBounds(0,0, min(width,height), min(width,height))
pieDrawable.draw(canvas)
}
}
/**
* @param values - 所有值数组
* @param colors - 值对应的颜色数组
*/
class PieDrawable(val values : Array<Float>,val colors:Array<Int>) : Drawable(){
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
override fun draw(canvas: Canvas) {
if (values.size != colors.size) {
return
}
val sum:Float = values.sum()
var startAngle = 0f
paint.style = Paint.Style.FILL_AND_STROKE
for(i in 0 until values.size) {
val sweepAngle = (values[i]/sum) * 360
paint.color = colors[i]
canvas.drawArc(bounds.toRectF(),startAngle,sweepAngle,true,paint)
startAngle += sweepAngle
}
}
/**
* @param alpha - 范围[0-25],0表示完全透明,255完全不透明
* 用于设置图片的透明度,简单的一个做法时直接将该值赋值为 paint.alpha.
*/
override fun setAlpha(alpha: Int) {
paint.alpha = alpha
}
override fun getAlpha(): Int {
return paint.alpha;
}
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.colorFilter = colorFilter
}
/**
* 用于判断上层绘制和下层绘制重叠时的融合规则
*/
override fun getOpacity(): Int {
return when(paint.alpha) {
// 透明模式
0 -> PixelFormat.TRANSLUCENT
// 不透明模式
0xff -> PixelFormat.OPAQUE
// 半透明模式
else -> PixelFormat.TRANSLUCENT
}
}
}