使用 Android Widget 组中不存在的自定义 UI 元素并想知道它是如何制作的?

这是 Android 中存在的 Canvas API 的魔力。我认为画布这个名字本身就定义了它是艺术家的游乐场,你必须展示你最好的艺术。

在这个博客中,我们将了解我们将如何学习,

  • 什么是 Android 中的 Canvas API?
  • 了解Canvas实现。
  • 我们如何使用 canvas API 制作自己的 UI 元素?

什么是Android 中的Canvas API?

Android 中的 Canvas API 是一个绘图框架,可帮助我们绘制自定义设计,如线条、圆形甚至矩形。使用这些我们可以根据设计制作任何我们想要的形状。

画布的绘制发生在位图中,我们在其中绘制轮廓,然后 Paint API 帮助填充颜色和我们需要的任何样式。

Canvas有助于创建骨架,而油漆有助于美化设计。

了解Canvas实现

所以,既然我们知道 Canvas 有助于设计视图,那么让我们了解一下视图的渲染方式。有一些布局方法被调用,它们是

android 图形图像处理 安卓 图形api_API

在这里,onMeasure() - 测量视图和那里的孩子的大小,onLayout() - 有助于设置大小,而 onDraw() 是有助于在视图上绘制的。

因此,在 onDraw() 中,Canvas用于使用其预先包含的方法进行绘制,例如 drawLine、drawArc 等。但是,画布实际上是如何在屏幕上绘制自身的呢?

Canvas 遵循坐标系在屏幕上绘制自身。它将手机屏幕视为自己的坐标系。

看下图感受一下

android 图形图像处理 安卓 图形api_Android_02

所以在这里

  • 左上角代表坐标系中的 (0,0) 点。
  • 然后右下角是坐标系中的 (x,y) 点。
  • 因此,以这种方式,屏幕的中心由 (x/2,y/2) 点表示。

到目前为止,我们已经了解了如何使用 Canvas 以及在画布上绘图时需要注意哪些因素。现在,让我们看看如何使用画布实际绘制。

要绘制我们自己的自定义绘图,我们可以在自己的视图类中进行。在这里,我将创建自己的 CanvasView,

class CanvasView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        //here we have to use the canvas API to draw
    }
}

如您所见,在 onDraw() 中,我们将绘制我自己的设计。

现在,要在 Canvas 上绘图,我们需要视图类中的Paint对象。所以要定义油漆,

定义油漆,我将使用

private val myViewPaint =
    Paint().apply {
        isAntiAlias = true
        color = Color.BLACK
        style = Paint.Style.STROKE
    }

在这里,我已经初始化了绘制对象,并为其设置了一个自定义属性,例如颜色和样式,以存储要在画布上绘制的信息。

isAntiAlias - 用于在绘制时使边缘平滑。

现在,让我们从在画布上画一条线开始。在, onDraw() 我会写,

canvas?.drawLine(0f, 5f, 0f, 10f, myViewPaint)

在这里,drawLine() 采用两点坐标和油漆来绘制自身。在上面的代码中,0f 和 5f 是第一个点的 x 和 y 坐标,0f 和 10f 是第二个点的坐标。

同样,我们也可以使用Path()来代替通过点坐标来绘制自定义形状。

路径用于通过将形状从一个点传递到另一个点来绘制形状。要使用 Path 绘制一条线,我们必须使用,

val path = Path().apply {
    moveTo(x1, y1)
    lineTo(x2, y2)
    close()
}
canvas?.drawPath(path, myViewPaint)

在这里,在上面的代码中,我们使用了一条路径来绘制一条线。让我逐行分解以使您理解。

moveTo - 这用于将绘图尖端从一个点移动到另一个点。所以这里的绘图提示已经移动到 (x1, y1)。

lineTo - 用于从 (x1,y1) 到 (x2, y2) 画一条线。当我们移动到 (x1, y1) 时,这将是我们画线的起点。

PS。使用路径,您可以绘制您想要的任何类型的形状。

现在,为了使用路径画线,我们需要使用 canvas.drawPath 而不是之前代码中使用的 canvas.drawLine。

同样,要画一个圆,我们使用

canvas?.drawCircle(x,y,radius,myViewPaint)

其中 x 和 y 是该点的坐标,我们通过圆的半径。

现在,为了最终在屏幕上绘制它,我们在视图的 onDraw 中调用 invalidate()。

要在 Activity 中使用上述 View 类,我们只需在 XML 文件中使用以下内容,

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <app.himanshu.playground.CanvasView
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
</LinearLayout>

要记住的要点,

  • 由于绘制发生在主 UI 线程上,请避免在同一部分重新绘制时间过长。
  • 不要在 onDraw() 中进行大量计算
  • 画布适用于像素而不是 dp。