Bitmap 和 Drawable 相关整理

Author Avatar
dev.liang 2月 27, 2019
  • 在其它设备中阅读本文章

Bitmap 和 Drawable 本质区别是什么,来一起简单了解下它的本质吧…

Bitmap 和 Drawable 本质区别

Bitmap 是什么?

字面理解是位图,位图就是一个图像的完整数据

1
2
3
4
5
6
image:width:640;height:640;0000ff0000ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff000
0ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff000
0ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff
0000ff0000ff0000ff

在内存里以位图形式存储一个图片的所有像素信息,可以用上面的形式来表示。

Drawable 是什么?

Drawable 更像是一个抽象版的自定义的 view,但 Drawable 只负责绘制,只是一个绘制工具。Drawable 不是一个被绘制的对象(path、circle、line 等等都是被 canvas 绘制的对象),更像是一个 view,它持有 canvas,只负责绘制,它想怎么绘制就按照自己规则去绘制。Drawable 内部存储的是一个绘制规则,这个规则可以是一个具体的一个具体的 bitmap、颜色、抽象的灵活的描述,Drawable 是不能含有具体的像素信息。

用代码简单举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class DrawableView extends View {
Drawable drawable;

public DrawableView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

{
drawable = new ColorDrawable(Color.RED);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawable.setBounds(100, 100, getWidth(), getHeight());
drawable.draw(canvas);
}
}

自定义 Drawable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class DrawableView extends View {
Drawable drawable;

public DrawableView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

{
drawable = new MeshDrawable();
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// drawable.setBounds(100, 100, getWidth(), getHeight());
drawable.setBounds(0, 0, getWidth(), getHeight());
drawable.draw(canvas);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class MeshDrawable extends Drawable {
private static final int INTERVAL = (int) Utils.dpToPixel(80);

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

{
paint.setColor(Color.RED);
paint.setStrokeWidth(Utils.dpToPixel(2));
}

@Override
public void draw(@NonNull Canvas canvas) {
for (int i = 0; i < getBounds().right; i += INTERVAL) {
System.out.println("外 i = " + i );
for (int j = 0; j < getBounds().bottom; j += INTERVAL) {
System.out.println("内 i = " + i + " j = " + j);
// 画 横线
canvas.drawLine(getBounds().left, j, getBounds().right, j, paint);
// 画 竖线
canvas.drawLine(i, getBounds().top, i, getBounds().bottom, paint);
}
}
}

@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}

@Override
public int getAlpha() {
return paint.getAlpha();
}

@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
}

@Override
public int getOpacity() {
return paint.getAlpha() == 0 ? PixelFormat.TRANSPARENT :
paint.getAlpha() == 0xff ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
}
}

Bitmap 和 Drawable 之间互相转换

1
2
// bitmap --> Drawable
Drawable drawble = new BitmapDrawable(getResources(),bitmap);

这两个类本身就不是一个概念,就不存在相互转换的操作,如果真有这样的需求,也是可以实现效果。 如果非要 Drawable –> bitmap 转换,就只能硬画了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Drawable --> bitmap

/* 调用*/
Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
R.drawable.icon_resource);

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) {
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
} 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;
}