Jetpack Compose 中 Canvas 的重新组合

4
我正在使用Jetpack Compose实现“逐渐增长的线”的要求,即从指定的起始点开始,逐渐“增长”到达指定的终点的线条。
我之前使用自定义视图实现了这个功能,效果很好。但是我的逻辑需要根据某些条件不断地重新调用"onDraw()"方法。在使用自定义视图时,我使用了"invalidate()"方法来实现这一点。但是现在我正在使用Jetpack Compose,却无法找到重新组合“Canvas”的方法。
以下是我的Jetpack Compose代码示例:
   @Composable
        fun SplashUI() {
            var test = remember { mutableStateOf(0) }
                Canvas(modifier = Modifier.fillMaxSize()) {
                    //  starting point
                    x1 = 0.0;
                    y1 = size.height / 2.0;

                    //  ending point
                    x2 = size.width.toDouble()
                    y2 = size.height / 2.0;

                    divideLineIntoEqualParts();

                    if (test.value < listOfPoints.size) {
                        drawLine(
                            Color.Black,
                            Offset(
                                listOfPoints.get(0)?.x!!,
                                listOfPoints.get(0)?.y!!
                            ),
                            Offset(
                                listOfPoints.get(inte)?.x!!,
                                listOfPoints.get(inte)?.y!!
                            ),
                            strokeWidth = 5f
                        );
                    }
                    test.value = test.value + 1 //This doesn't trigger recomposition of canvas
                    //Recomposition of Canvas should happen after the above step for my logic to work

                   //I had implemented this earlier using custom view, and used 'invalidate()' like:
                   /* if (inte < listOfPoints.size) {
                        invalidate()
                    }*/
            }
        }


    private fun divideLineIntoEqualParts() {
        listOfPoints.clear()
        for (k in 1..50) {
            listOfPoints.add(PointF((x1 + k * (x2 - x1) / 50).toFloat(),
                (y1 + k * (y2 - y1) / 50).toFloat()
            ))
        }
        Log.d("listOfPoints : size : ", listOfPoints.size.toString() + "")
    }

请建议一种重新组合Canvas的方法,或者其他使我的逻辑能够工作的方式。

你发布的代码包含太多语法错误。 - Rafsanjani
3个回答

7

我同意 Gabriele Mariotti 的回答,但有时您需要控制权以便能够随时在画布上重绘!

我正在尝试开发一个绘图应用程序,在触摸事件发生时必须使其失效!

在这篇文章Simple Jetpack Drawing App中,通过 MotionEvent 的动作更改来使画布无效,因此每次运动事件的动作更改都可以使画布无效(重新绘制)。

我们可以使用相同的逻辑。

var invalidations by remember{
    mutableStateOf(0)
}

现在在Canvas Composable中

Canvas {
    invalidations.let{inv->
        //Draw Composables
    }
}

现在,每当您想要使其无效:
invalidations++

这并不是最好的做法,因为改变一个变量的状态只会导致该组件重新绘制,但这样失效化将重新绘制在失效化内部绘制的任何内容。让 block !


1
Canvas使用的DrawScope不是一个可组合的元素,因此只需要在Canvas内部引用invalidations变量即可。无法将draw操作拆分为只绘制某些元素的方式。要么不绘制任何东西,要么绘制全部。当然,简单地引用该变量会导致IDE警告未使用,但可以通过invalidations.apply {}解决 - 对我来说完全有效。 - undefined

2
为了模拟一个定时游戏循环,你可以使用withFrame function family
LaunchedEffect(Unit) {
    while (true) {
        withFrameNanos {
            game. Update(it)
        }
    }
}

原始代码


1
有一些不同之处。
问题中的代码在Android的View中工作,您正在onDraw方法中绘制Canvas。您正在绘制将可用空间(=宽度)分成点的水平线。
在Compose中,您只需将Canvas用作Composable,并可以动画化线条的长度。 类似于:
//Animation - it will be repeated 2 times
val animatedProgress = remember { Animatable(0.001f) }
LaunchedEffect(animatedProgress) {
    animatedProgress.animateTo(1f,
        animationSpec = repeatable(2,
            animation = tween(durationMillis = 3000, easing = LinearEasing)
        ))
}

Canvas(modifier = Modifier.fillMaxSize() ) {

    val startingPoint = Offset(0f, size.height / 2f)
    val endingPoint = Offset(size.width * animatedProgress.value, size.height / 2f)

    //At the end of animation just remove the line
    if (animatedProgress.isRunning) {
        drawLine(
            strokeWidth = 8.dp.toPx(),
            color = Color.Black,
            start = startingPoint,
            end = endingPoint
        )
    }
}

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接