[Jetpack compose]使用Canvas实现画板的功能

1,153 阅读1分钟

实现逻辑(与使用自定义view实现相似)

  • 在Modifier.pointerInteropFilter中监听触摸事件,记录触摸的点x,y,调用path.moveTo(x,y)和path.lineTo(x,y)来绘制线条

  • 在canvas的onDraw{ }中调用drawPath()来绘制路径,并使用downX使其进行recompose

  • 调用path.reset()来清除已绘制的内容

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun MyCanvas() {
    //记录初始按下的点
    var downX by remember {
        mutableStateOf(0f)
    }
    var downY by remember {
        mutableStateOf(0f)
    }
    //绘制路径
    val path = Path()

    Box(modifier = Modifier.fillMaxSize(),contentAlignment = Alignment.BottomCenter) {
        Canvas(modifier = Modifier
            .fillMaxSize()
            //使用pointerInteropFilter来获取触摸事件
            .pointerInteropFilter { event ->
                when (event.action) {
                    MotionEvent.ACTION_DOWN -> {
                        //按下屏幕时,path移动到点击的地方
                        downX = event.x
                        downY = event.y
                        path.moveTo(downX, downY)
                    }
                    MotionEvent.ACTION_MOVE -> {
                        //手指移动时,绘制线条,并重置downX和downY
                        path.lineTo(downX, downY)
                        downX = event.x
                        downY = event.y
                    }
                }
                true
            }, onDraw = {
            //在这里使用一下这个变量,当downX发生变化时,进行recompose
            downX
            //把记录的path绘制出来
            drawPath(
                path,
                color = Color.Red,
                style = Stroke(width = 20f, cap = StrokeCap.Round, join = StrokeJoin.Round)
            )
        })

        //给画板添加清除的功能
        //在button的onClick事件中,调用path.reset(),再将downX置为0触发Canvas的recompose即可
        Button(onClick = {
            path.reset()
            downX = 0f
        }) {
            Text(text = "清除全部")
        }
    }
}

效果图

Video_20220114_121729_791.gif