Jetpack Compose - 使用指针输入处理像素精确可组合项的最佳方法

问题描述 投票:0回答:1

Jetpack Compose 似乎专门用于相对于 UI 的其余部分自动定位和调整大小的 UI,而无需知道其确切大小。这在很多情况下都很棒,但我有一些应用程序需要一个可组合项来以精确的像素坐标和大小进行绘制。我还需要跟踪可组合项上的指针输入,以可组合项大小的百分比表示。

我现在正在处理的具体情况是显示一个钢琴键盘,如图所示,其中每个键都需要调整大小并放置在相对于整个键盘的特定位置。另外,我需要跟踪键盘内的指针并计算按下了哪些键。我目前正在使用 Canvas 可组合项来实现它。画布为您提供其大小很有帮助,但我无法在画布范围之外使用该大小来跟踪指针输入。这是我目前的计划。

    var width by remember { mutableStateOf(0) }
    var height by remember { mutableStateOf(0) }

    Canvas(modifier = modifier
        .background(Color.Black)
        .pointerInput(width, height) {
            awaitPointerEventScope {
                 /* track pointers and calculate which
                 keys are pressed using the values of
                 width and height */
            }
        }.onSizeChanged {
            width = it.width
            height = it.height
        }
    ) {
        /* draw the piano keys, using the values
        of size.width and size.height to size and
        position them */
    }

我的问题是:

  1. 使用 .onSizeChanged 修饰符来跟踪大小似乎很糟糕。有没有更好的办法?我还担心,当指针输入范围被取消并在大小发生变化时重新启动时,这样做会导致错误,这可能会导致一些指针事件丢失。
  2. 完全使用画布渲染更大的 UI 组件(例如钢琴键盘)通常可以接受吗?我将有按键动画,并且使用画布意味着整个键盘将在动画的每一帧上重新绘制。手动实现某种缓冲区或缓存以避免重绘组件是否很常见,或者绘制一堆简单形状的速度太快以至于通常并不重要?
android android-jetpack-compose android-canvas
1个回答
0
投票

首先,如果您不为

Modifier
分配任何大小
Canvas
,则从
size
获得的
DrawScope
将具有 0 宽度和高度。在 Jetpack Compose 中,只要您不需要此尺寸参数,您就可以在任何地方绘制而无需设置它,但如果您检查日志,您会发现它将具有零宽度和高度。

1-您不需要

onSizeChanged
,因为
PointerInputScope
也会返回
size
,这是相同的
size
,除非您在此之后设置任何填充或其他布局修饰符。

如果您想重置pointerInputScope,您可以使用

BoxWithConstraint
as

获取屏幕宽度和高度
@Preview
@Composable
private fun Test() {
    BoxWithConstraints(
        modifier = Modifier.fillMaxSize()
    ) {

        val width: Dp = maxWidth
        val height: Dp = maxHeight

        Canvas(
            modifier = Modifier.background(Color.Black)
                .pointerInput(width, height) {
                    
                    // The size you get from PointerInputScope is same as you get from 
                    // DrawScope unless you set padding or another layout modifier
                    
                    val size: IntSize = this.size
                    
                    awaitPointerEventScope {
                        /* track pointers and calculate which
                        keys are pressed using the values of
                        width and height */
                    }
                }
        ) {
            
            val size = this.size
            println("size: $size")
            
            /* draw the piano keys, using the values
            of size.width and size.height to size and
            position them */
        }
        
    }
}

2- Canvas 是一个带有 Modifier.drawBehind 的 Spacer,在此范围内执行的任何操作都仅调用 google 建议的合成的绘制阶段,尤其是对于动画。

https://developer.android.com/jetpack/compose/performance/bestpractices#defer-reads

查看背景动画片段。

© www.soinside.com 2019 - 2024. All rights reserved.