You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose Canvas重绘时保留历史绘制图形的实现问询

实现方案

核心思路

你当前代码仅存储了单个最新选中的图形标识,Canvas每次重组时只会绘制当前这一个图形,所以无法保留历史内容。我们不需要记录DrawScope的状态,只需维护一个历史图形队列的可变状态即可:

  • 每次点击按钮时,把新选中的图形配置添加到队列中
  • Canvas绘制时遍历队列,依次绘制所有历史图形即可保留全部内容

具体实现代码

第一步:定义图形配置数据类

用来存储每个图形的参数,后续可扩展大小、位置等属性

data class DrawingShape(
    val type: String, // 图形类型:Circle/Rectangle/Oval
    val color: Color
)

第二步:修改布局代码

@Composable
fun PaintBrushLayout(
    modifier: Modifier = Modifier,
) {
    // 替换原来的单值状态,改为存储所有历史图形的可变列表
    val shapeList = remember {
        mutableStateListOf<DrawingShape>()
    }

    Column(
        verticalArrangement = Arrangement.Bottom, modifier = modifier.fillMaxSize()
    ) {
        Canvas(
            modifier = Modifier
                .fillMaxWidth()
                .fillMaxHeight(.9f)
        ) {
            // 遍历所有历史图形依次绘制
            shapeList.forEach { shape ->
                when (shape.type) {
                    "Circle" -> {
                        drawCircleFig(color = shape.color)
                    }
                    "Rectangle" -> {
                        drawRectangleFig(color = shape.color)
                    }
                    "Oval" -> {
                        drawOvalFig(color = shape.color)
                    }
                }
            }
        }

        Row(
            modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween
        ) {
            BottomLayout("Circle") { _, _ ->
                // 点击时往列表添加对应图形配置
                shapeList.add(DrawingShape("Circle", Color.Blue))
            }
            BottomLayout("Rectangle") { _, _ ->
                shapeList.add(DrawingShape("Rectangle", Color.Red))
            }
            BottomLayout("Oval") { _, _ ->
                shapeList.add(DrawingShape("Oval", Color.Gray))
            }
            BottomLayout("Choose Color") { _, _ ->
                // 颜色选择逻辑可自行扩展,选中后修改后续添加图形的颜色即可
            }
        }
    }
}

@Composable
fun BottomLayout(
    btnName: String,
    click: (Boolean, String) -> Unit
) {
    Button(onClick = {
        click(true, btnName)
    }, modifier = Modifier.padding(4.dp)) {
        Text(text = btnName)
    }
}

fun DrawScope.drawCircleFig(color: Color = Color.Red) {
    drawCircle(
        color = color
    )
}

fun DrawScope.drawRectangleFig(color: Color = Color.Red) {
    drawRect(
        color = color
    )
}

fun DrawScope.drawOvalFig(color: Color = Color.Red) {
    drawOval(
        color = color
    )
}

优化建议

如果不想所有图形都重叠在一起,可以在DrawingShape中添加center: Offset、size: Size等参数,每次点击按钮添加图形时随机生成这些参数,即可实现不同位置大小的图形绘制效果。


内容的提问来源于stack exchange,提问作者hemant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 20:54:03