ITmob-Ly
发布于 2024-03-15 / 251 阅读
0

Jetpack Compose 中三个绘图修饰符 drawWithContent, drawBehind, drawWithCache 的区别和用法

Jetpack Compose 中除了 Canvas 可组合项之外,Compose 还有三个可用于图形绘制的 Modifier/修饰符:drawBehind, drawWithContent, drawWithCache,它们可以应用于任何可组合项。

在本文中,我们将介绍 Jetpack Compose 中的 drawBehind, drawWithContent , drawWithCache 的区别和用法。

drawWithContent

drawWithContent 是绘图的基本修饰符,可以在其中决定绘图顺序。

通过修改在 drawWithContent 中调用 drawContent 的调用位置实现绘图时可组合项的内容的绘制顺序。

例如,在包含一个 TextBox 可组合项前面绘制半透明的蓝色遮罩层:

Text and a translucent foreground drawn using Modifier.drawWithContent

@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 方法,它同样接受一个接收者类型为 DrawScopelambda 表达式为参数。

drawBehind

drawBehinddrawWithContent 的一个方便使用的封装,它将绘图顺序设置为可组合内容的后面。

例如,通过 drawBehindText 绘制一个蓝色的圆角背景:

Text and a background drawn using Modifier.drawBehind

@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 可以绘制图形并缓存在其中创建的对象,只要绘图区域的大小相同,或者读取的任何状态对象都没有更改,就会缓存对象。

这个修饰符有助于提高绘图调用的性能,因为它避免了重新分配在绘图时创建的对象(如: BrushShaderPath 等)。

注意: 只有在需要创建必须缓存的对象时才使用 Modifier.drawWithCache ,不需要缓存对象时使用此修饰符,可能会导致不必要的lambda分配。

例如,如果通过 BrushText 后面绘制渐变背景,则可以使用 drawWithCache 来缓存 Brush ”对象,直到绘图区域的大小发生变化:

Caching the Brush object with drawWithCache

@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 来绘制图形。

总结

  1. 绘图的基本修饰器是 drawWithContent,在其中可以修改组合项与绘制内容的绘制顺序。
  2. drawBehind 是用于方便调用的 drawWithContent 的包装,它的绘图顺序固定为绘制内容在可组合内容的后面。
  3. drawWithCache 在其内部调用 onDrawBehindonDrawWithContent 来绘制,并可以缓存在其中创建的对象。

更多相关文章:

https://developer.android.com/jetpack/compose/graphics/draw/modifiers

Jetpack Compose 中 Canvas 绘制图形的基本用法