Jetpack Compose 中除了 Canvas 可组合项之外,Compose 还有三个可用于图形绘制的 Modifier/修饰符:drawBehind, drawWithContent, drawWithCache,它们可以应用于任何可组合项。
在本文中,我们将介绍 Jetpack Compose 中的 drawBehind, drawWithContent , drawWithCache 的区别和用法。
drawWithContent
drawWithContent 是绘图的基本修饰符,可以在其中决定绘图顺序。
通过修改在
drawWithContent中调用drawContent的调用位置实现绘图时可组合项的内容的绘制顺序。
例如,在包含一个 Text 的 Box 可组合项前面绘制半透明的蓝色遮罩层:

@Composable
fun DrawWithContentSample() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Column(
modifier = Modifier
.drawWithContent {
drawContent() // 先调用 drawContent() 则先绘制可组合项的内容
drawRoundRect(
color = Color.Blue,
alpha = 0.6f,
cornerRadius = CornerRadius(16.dp.toPx(), 16.dp.toPx()),
)
}
.padding(16.dp),
) {
Text("Hello itmob.cn")
}
}
}
我们调用了 drawWithContent 方法,它同样接受一个接收者类型为 DrawScope 的 lambda 表达式为参数。
drawBehind
drawBehind 是 drawWithContent 的一个方便使用的封装,它将绘图顺序设置为可组合内容的后面。
例如,通过 drawBehind 为 Text 绘制一个蓝色的圆角背景:

@Composable
fun DrawBehindSample() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Text(
text = "Hello itmob.cn",
modifier = Modifier
.drawBehind {
drawRoundRect(
color = Color.Blue,
cornerRadius = CornerRadius(16.dp.toPx(), 16.dp.toPx()),
)
}
.padding(16.dp),
color = Color.White,
)
}
}
drawBehind方法拥有一个名为 onDraw,接收者为DrawScope类型的lambda表达式,我们在这个lambda中使用DrawScope提供的字段和函数进行绘制。
drawWithCache
drawWithCache 可以绘制图形并缓存在其中创建的对象,只要绘图区域的大小相同,或者读取的任何状态对象都没有更改,就会缓存对象。
这个修饰符有助于提高绘图调用的性能,因为它避免了重新分配在绘图时创建的对象(如:
Brush,Shader,Path等)。
注意: 只有在需要创建必须缓存的对象时才使用 Modifier.drawWithCache ,不需要缓存对象时使用此修饰符,可能会导致不必要的lambda分配。
例如,如果通过 Brush 在 Text 后面绘制渐变背景,则可以使用 drawWithCache 来缓存 Brush ”对象,直到绘图区域的大小发生变化:

@Composable
fun DrawWithCacheSample() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Text(
text = "Hello itmob.cn",
color = Color.White,
modifier = Modifier
.drawWithCache {
// 这里创建的对象将被缓存,直到绘图区域发生变化。
val brush = Brush.linearGradient(
listOf(
Color(0xFF9E82F0),
Color(0xFF42A5F5),
),
)
onDrawBehind {
drawRoundRect(
brush = brush,
cornerRadius = CornerRadius(16.dp.toPx()),
)
}
}
.padding(16.dp),
)
}
}
正如上例调用 drawWithCache 修饰符,它接受接收器为 CacheDrawScope 方法,通过 CacheDrawScope 我们可以调用 onDrawBehind 和 onDrawWithContent 来绘制图形。
总结
- 绘图的基本修饰器是
drawWithContent,在其中可以修改组合项与绘制内容的绘制顺序。 drawBehind是用于方便调用的drawWithContent的包装,它的绘图顺序固定为绘制内容在可组合内容的后面。drawWithCache在其内部调用onDrawBehind或onDrawWithContent来绘制,并可以缓存在其中创建的对象。
更多相关文章:
https://developer.android.com/jetpack/compose/graphics/draw/modifiers