自定义view⑥自定义Drawable

2,036 阅读2分钟

Bitmap

Bitmap 是位图信息的存储,即一个矩形图像每个像素的颜色信息的存储器。

Bitmap 和 Drawable 的互相转换

事实上,由于 Bitmap 和 Drawable 是两个不同的概念,因此确切地说它们并不是互 相「转换」,而是从其中一个获得另一个的对象:

  • Bitmap -> Drawable:创建一个 BitmapDrawable。
  • Drawable -> Bitmap:如果是 BitmapDrawable,使用 BitmapDrawable.getBitmap() 直接获取;如果不是,创建一个 Bitmap 和一个 Canvas,使用 Drawable 通过 Canvas 把内容绘制到 Bitmap 中。

Drawable

  • Drawable 是一个可以调用 Canvas 来进行绘制的上层工具。调用 Drawable.draw(Canvas) 可以把 Drawable 设置的绘制内容绘制到 Canvas 中。
  • Drawable 内部存储的是绘制规则,这个规则可以是一个具体的 Bitmap,也可以是 一个纯粹的颜色,甚至可以是一个抽象的、灵活的描述。Drawable 可以不含有具体 的像素信息,只要它含有的信息足以在 draw(Canvas) 方法被调用时进行绘制就 够了。
  • 由于 Drawable 存储的只是绘制规则,因此在它的 draw() 方法被调用前,需要先 调用 Drawable.setBounds() 来为它设置绘制边界。

自定义Drawable

自定义一个ColorDrawable的实现

ColorDrawable

class DrawableView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
  private val drawable = ColorDrawable(Color.RED)

  override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    drawable.setBounds(50.dp.toInt(), 80.dp.toInt(), width, height)
    drawable.draw(canvas)
  }
}

效果
33

网格线Drawable

  • 重写几个抽象方法
  • 重写 setAlpha() 的时候记得重写 getAlpha()
  • 重写 draw(Canvas) 方法,然后在里面做具体的绘制工作
  • 例如:MeshDrawable
class MeshDrawable:Drawable() {
  private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
    color = Color.parseColor("#F9A825")
    strokeWidth = 5.dp
  }
  private val INTERVAL = 50.dp

  override fun draw(canvas: Canvas) {
    //网格竖线
    var x = bounds.left.toFloat()
    while (x < bounds.right){
      canvas.drawLine(x,bounds.top.toFloat(),x, bounds.bottom.toFloat(),paint)
      x += INTERVAL
    }
    //网格横线
    var y = bounds.top.toFloat()
    while (y < bounds.bottom){
      canvas.drawLine(bounds.left.toFloat(),y, bounds.right.toFloat(),y,paint)
      y += INTERVAL
    }
  }
  ...
}

然后DrawableView中替换一下

private val drawable = MeshDrawable()

效果
34

用来干嘛?

  • 需要共享在多个 View 之间的绘制代码,写在 Drawable 里,然后在多个自 定义 View 里只要引用相同的 Drawable 就好,而不用互相粘贴代码。
  • 例如?
    • 股票软件的多个蜡烛图界面,可以把共享的蜡烛图界面放进去
      • 共用的Drawable
      //共用的Drawable
      class CandleDrawable : Drawable()
      
      • 简单的蜡烛view
      class SimpleCandleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
          val drawable = CandleDrawable()
          ...
      }
      
      • 复杂的蜡烛view
      class DetailedCandleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
          val drawable = CandleDrawable()
          ...
      }