许多应用需要能够精确控制屏幕上绘制的内容。这可能小到在屏幕上恰到好处地放置一个方框或圆形,也可能是在许多不同样式中精心安排图形元素。
使用修饰符和 DrawScope
进行基本绘制
在 Compose 中绘制自定义内容的核心方法是使用修饰符,例如 Modifier.drawWithContent
、Modifier.drawBehind
和 Modifier.drawWithCache
。
例如,要在您的可组合项后面绘制内容,您可以使用 drawBehind
修饰符来开始执行绘制命令
Spacer( modifier = Modifier .fillMaxSize() .drawBehind { // this = DrawScope } )
如果您只需要一个可绘制的可组合项,您可以使用 Canvas
可组合项。Canvas
可组合项是对 Modifier.drawBehind
的便捷封装。您可以像放置任何其他 Compose UI 元素一样,在布局中放置 Canvas
。在 Canvas
中,您可以精确控制元素的样式和位置来绘制它们。
所有绘制修饰符都公开一个 DrawScope
,这是一个维护自身状态的作用域绘制环境。这允许您为一组图形元素设置参数。DrawScope
提供了几个有用的字段,例如 size
,一个指定 DrawScope
当前尺寸的 Size
对象。
要绘制内容,您可以使用 DrawScope
上的众多绘制函数之一。例如,以下代码在屏幕左上角绘制一个矩形。
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F drawRect( color = Color.Magenta, size = canvasQuadrantSize ) }

要详细了解不同的绘制修饰符,请参阅《图形修饰符》文档。
坐标系
要在屏幕上绘制内容,您需要知道项目的偏移量(x
和 y
)和大小。对于 DrawScope
上的许多绘制方法,位置和大小由默认参数值提供。默认参数通常将项目定位在画布上的 [0, 0]
点,并提供一个填充整个绘图区域的默认 size
,如上例所示 - 您可以看到矩形位于左上角。要调整项目的大小和位置,您需要了解 Compose 中的坐标系。
坐标系的原点([0,0]
)位于绘图区域的左上角像素。当向右移动时,x
值增大;当向下移动时,y
值增大。
![A grid showing the coordinate system showing the top left [0, 0] and bottom right [width, height]](/static/develop/ui/compose/images/graphics/introduction/compose_coordinate_system_drawing.png)
例如,如果您想从画布区域的右上角到左下角绘制一条对角线,您可以使用 DrawScope.drawLine()
函数,并指定具有相应 x 和 y 位置的起始和结束偏移量。
Canvas(modifier = Modifier.fillMaxSize()) { val canvasWidth = size.width val canvasHeight = size.height drawLine( start = Offset(x = canvasWidth, y = 0f), end = Offset(x = 0f, y = canvasHeight), color = Color.Blue ) }
基本转换
DrawScope
提供转换功能,可更改绘制命令的执行位置或方式。
缩放
使用 DrawScope.scale()
按比例增加绘制操作的大小。像 scale()
这样的操作适用于相应 lambda 中的所有绘制操作。例如,以下代码将 scaleX
增加 10 倍,将 scaleY
增加 15 倍。
Canvas(modifier = Modifier.fillMaxSize()) { scale(scaleX = 10f, scaleY = 15f) { drawCircle(Color.Blue, radius = 20.dp.toPx()) } }

平移
使用 DrawScope.translate()
向上、向下、向左或向右移动绘制操作。例如,以下代码将绘制内容向右移动 100 像素,向上移动 300 像素。
Canvas(modifier = Modifier.fillMaxSize()) { translate(left = 100f, top = -300f) { drawCircle(Color.Blue, radius = 200.dp.toPx()) } }

旋转
使用 DrawScope.rotate()
围绕枢轴点旋转绘制操作。例如,以下代码将矩形旋转 45 度。
Canvas(modifier = Modifier.fillMaxSize()) { rotate(degrees = 45F) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }

rotate()
将旋转应用于当前绘制范围,这将使矩形旋转 45 度。内嵌
使用 DrawScope.inset()
调整当前 DrawScope
的默认参数,更改绘制边界并相应地平移绘制内容。
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F inset(horizontal = 50f, vertical = 30f) { drawRect(color = Color.Green, size = canvasQuadrantSize) } }
此代码有效地为绘制命令添加了内边距。

多重转换
要对您的绘制内容应用多重转换,请使用 DrawScope.withTransform()
函数,该函数创建并应用一个组合了所有所需更改的单一转换。使用 withTransform()
比对单个转换进行嵌套调用更高效,因为所有转换都在一个操作中一起执行,而不是 Compose 需要计算和保存每个嵌套转换。
例如,以下代码对矩形同时应用平移和旋转。
Canvas(modifier = Modifier.fillMaxSize()) { withTransform({ translate(left = size.width / 5F) rotate(degrees = 45F) }) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }

withTransform
同时应用旋转和平移,旋转矩形并将其向左移动。常见绘制操作
绘制文本
在 Compose 中绘制文本,通常可以使用 Text
可组合项。但是,如果您在 DrawScope
中或想手动自定义绘制文本,可以使用 DrawScope.drawText()
方法。
要绘制文本,请使用 rememberTextMeasurer
创建一个 TextMeasurer
,然后使用该测量器调用 drawText
。
val textMeasurer = rememberTextMeasurer() Canvas(modifier = Modifier.fillMaxSize()) { drawText(textMeasurer, "Hello") }

测量文本
文本绘制与其他绘制命令略有不同。通常,您会为绘制命令提供绘制形状/图像的大小(宽度和高度)。对于文本,有一些参数可以控制渲染文本的大小,例如字体大小、字体、连字和字间距。
使用 Compose,您可以使用 TextMeasurer
来获取文本的测量大小,具体取决于上述因素。如果您想在文本后面绘制背景,可以使用测量信息来获取文本所占区域的大小。
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixedWidth((size.width * 2f / 3f).toInt()), style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
此代码段会在文本上生成粉红色背景。

调整约束、字体大小或任何影响测量大小的属性都会导致报告新的大小。您可以为 width
和 height
设置固定大小,然后文本会遵循设置的 TextOverflow
。例如,以下代码将文本渲染为可组合区域高度的 ⅓ 和宽度的 ⅓,并将 TextOverflow
设置为 TextOverflow.Ellipsis
。
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixed( width = (size.width / 3f).toInt(), height = (size.height / 3f).toInt() ), overflow = TextOverflow.Ellipsis, style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
文本现在在约束中绘制,末尾带有省略号。

TextOverflow.Ellipsis
在测量文本时具有固定约束。绘制图像
要使用 DrawScope
绘制 ImageBitmap
,请使用 ImageBitmap.imageResource()
加载图像,然后调用 drawImage
。
val dogImage = ImageBitmap.imageResource(id = R.drawable.dog) Canvas(modifier = Modifier.fillMaxSize(), onDraw = { drawImage(dogImage) })

ImageBitmap
。绘制基本形状
DrawScope
上有许多形状绘制函数。要绘制形状,请使用其中一个预定义的绘制函数,例如 drawCircle
。
val purpleColor = Color(0xFFBA68C8) Canvas( modifier = Modifier .fillMaxSize() .padding(16.dp), onDraw = { drawCircle(purpleColor) } )
API |
输出 |
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
绘制路径
路径是一系列数学指令,执行后会生成一个图形。DrawScope
可以使用 DrawScope.drawPath()
方法绘制路径。
例如,假设您想绘制一个三角形。您可以使用绘图区域的大小,通过 lineTo()
和 moveTo()
等函数生成一条路径。然后,使用此新创建的路径调用 drawPath()
以获得一个三角形。
Spacer( modifier = Modifier .drawWithCache { val path = Path() path.moveTo(0f, 0f) path.lineTo(size.width / 2f, size.height / 2f) path.lineTo(size.width, 0f) path.close() onDrawBehind { drawPath(path, Color.Magenta, style = Stroke(width = 10f)) } } .fillMaxSize() )

Path
。访问 Canvas
对象
使用 DrawScope
,您无法直接访问 Canvas
对象。您可以使用 DrawScope.drawIntoCanvas()
获取对 Canvas
对象本身的访问权限,您可以在其上调用函数。
例如,如果您有一个自定义的 Drawable
想绘制到画布上,您可以访问画布并调用 Drawable#draw()
,传入 Canvas
对象。
val drawable = ShapeDrawable(OvalShape()) Spacer( modifier = Modifier .drawWithContent { drawIntoCanvas { canvas -> drawable.setBounds(0, 0, size.width.toInt(), size.height.toInt()) drawable.draw(canvas.nativeCanvas) } } .fillMaxSize() )

Drawable
。了解详情
有关 Compose 中绘制的更多信息,请查看以下资源:
- 图形修饰符 - 了解不同类型的绘制修饰符。
- 画笔 - 了解如何自定义内容的绘制。
- Compose 中的自定义布局和图形 - Android 开发者峰会 2022 - 了解如何在 Compose 中使用布局和图形构建自定义 UI。
- JetLagged 示例 - 显示如何绘制自定义图表的 Compose 示例。
为您推荐
- 注意:当 JavaScript 关闭时显示链接文本
- 图形修饰符
- Compose 中的图形
- Jetpack Compose 中的对齐线