繁体   English   中英

Jetpack Compose 中 Canvas 的重组

[英]Recomposition of Canvas in Jetpack Compose

我正在使用 Jetpack Compose 来实现绘制“逐渐增长线”的要求,即从指定起点和点开始并逐渐“增长”直到到达指定终点的线。 我之前用自定义视图实现了这个,效果很好。 我的逻辑要求根据某些条件一次又一次地重新调用“onDraw()”。 为此,我在使用自定义视图时使用了“invalidate()”。 但现在我正在使用 Jetpack Compose,无法找到重新组合“Canvas”的方法。

这是我的 Jetpack 编写“渐进线”的代码:

   @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 的方法,或其他一些使我的逻辑工作的方法。

有一些差异。
问题中的代码在 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
        )
    }
}

在此处输入图像描述

我同意Gabriele Mariotti的回答,但我发现有时您需要控制以便能够在 canvas 中随时重绘!

我正在尝试开发一个用于绘图的应用程序,当触摸事件发生时,我必须使之无效!

在本文中, 简单的 Jetpack 绘图应用程序canvas 因 MotionEvent 的动作变化而失效,因此每次动作事件的动作变化时,canvas 都可以失效(重绘)

我们可以使用相同的逻辑

val invalidations = remember{
    mutableStateOf(0)
}

现在在 Canvas 可组合

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

现在,每当您想使无效时:

invalidations.value = invalidations.value++

这不是最好的方法,因为更改一个变量的 state 只会导致可组合重绘但以这种方式无效将重绘在 invalidations.let 块内绘制的任何内容!

要模拟定时游戏循环,您可以使用withFrame function 系列

LaunchedEffect(Unit) {
    while (true) {
        withFrameNanos {
            game. Update(it)
        }
    }
}

资源

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM