kotlin 如何获得我的可组合函数/子函数的绝对位置?

kupeojn6  于 2022-11-16  发布在  Kotlin
关注(0)|答案(1)|浏览(207)

我试过用this来回答他用OnGloballyPositionedModifier的问题,但它没有返回我孩子的正确绝对位置。我试过positionInWindow()positionInRoot()。当column做间距时,它似乎工作,但当我用offset做时,它不工作。

@Composable
fun GetAbsolutePos(
    content: @Composable () -> Unit,
) {
    Box(modifier = Modifier
        .onGloballyPositioned { coordinates ->
            println("My coordinates: " + coordinates.positionInRoot())
        }
    ) {
        content()
    }

}

@Preview
@Composable
fun test() {
    GetAbsolutePos() {
        Box(
            modifier = Modifier
                .width(PixelToDp(pixelSize = 200))
                .offset(x = PixelToDp(pixelSize = 100), y = PixelToDp(pixelSize = 50))
                .height(PixelToDp(pixelSize = 200))
                .background(Color.Red)
        ) {
            GetAbsolutePos() {
                Column(
                ) {
                    GetAbsolutePos() {
                        Box(
                            Modifier
                                .size(PixelToDp(pixelSize = 20))
                                .background(Color.Green)
                        )
                    }
                    GetAbsolutePos() {
                        Box(
                            Modifier
                                .size(PixelToDp(pixelSize = 20))
                                .background(Color.Blue)
                        )
                    }
                }
            }
        }
    }
}

它将打印以下内容

I/System.out: My coordinates: Offset(0.0, 0.0)    // wrong I used offset, it should be 100x50
I/System.out: My coordinates: Offset(100.0, 50.0) // correct
I/System.out: My coordinates: Offset(100.0, 50.0) // correct
I/System.out: My coordinates: Offset(100.0, 70.0) // correct? so it works on column spacing but not with offset????

有没有办法得到我的组合函数相对于整个ANDROID窗口的绝对位置?

编辑1:

@Composable
fun PixelToDp(pixelSize: Int): Dp {
    return with(LocalDensity.current) { pixelSize.toDp() }
}

编辑:2

修饰符的顺序应该无关紧要,因为函数onGloballyPositioned声明了。
This callback will be invoked at least once when the LayoutCoordinates are available, and every time the element's position changes within the window.
对于onSizeChanged也是如此,可以通过运行下面的代码来观察(与@Thracian的答案中的示例相同)。
Invoked with the size of the modified Compose UI element when the element is first measured or when the size of the element changes.
因为这个函数实际上是一个回调函数,所以顺序应该不重要。如果我错了,请随时纠正我。

Box(modifier = Modifier
        .onSizeChanged {
            println("🔥 Size 1: $it")
        }
        .size(PixelToDp(pixelSize = 150))
        .onSizeChanged {
            println("🔥 Size 2: $it")
        }
        .background(Color.Red)
    )

打印

I/System.out: 🔥 Size 2: 150 x 150
I/System.out: 🔥 Size 1: 150 x 150
zu0ti5jz

zu0ti5jz1#

检查合成对象的位置时,未考虑修改器的顺序问题

Box(modifier = Modifier
    .onGloballyPositioned {
      val positionInRoot =  it.positionInRoot()
        println("🔥 POSITION 1: $positionInRoot")
    }
    .offset {
        IntOffset(100,50)
    }
    .onGloballyPositioned {
        val positionInRoot =  it.positionInRoot()
        println("🔥🔥 POSITION 2: $positionInRoot")
    }
    .size(100.dp)
    .background(Color.Red)
)

印刷品:

🔥 POSITION 1: Offset(0.0, 0.0)
🔥🔥 POSITION 2: Offset(100.0, 50.0)

在这个答案中,我解释了修改器的顺序如何改变一些修改器的结果,包括修改器。偏移量
https://stackoverflow.com/a/74145347/5457853
我做了一个例子来展示与兄弟、其他修改器的交互,以及基于修改器如何应用于Modifier.offset或Modifier.graphicsLayer的位置

@Composable
private fun OffsetAndTranslationExample() {
    val context = LocalContext.current

    var value by remember { mutableStateOf(0f) }

    var positionBeforeOffset by remember {
        mutableStateOf("Offset.Zero")
    }

    var positionAfterOffset by remember {
        mutableStateOf("Offset.Zero")
    }


    Row(modifier = Modifier.border(2.dp, Color.Red)) {
        Box(
            modifier = Modifier
                .onGloballyPositioned {
                    positionBeforeOffset = "Position before offset: ${it.positionInRoot()}"
                }
                .offset {
                    IntOffset(value.toInt(), 0)
                }
                .onGloballyPositioned {
                    positionAfterOffset = "Position after offset: ${it.positionInRoot()}"
                }
                .clickable {
                    Toast
                        .makeText(context, "One with offset is clicked", Toast.LENGTH_SHORT)
                        .show()
                }
                .zIndex(2f)
                .shadow(2.dp)
                .border(2.dp, Color.Green)
                .background(Orange400)
                .size(120.dp)
        )
        Box(
            modifier = Modifier
                .zIndex(1f)
                .background(Blue400)
                .size(120.dp)
                .clickable {
                    Toast
                        .makeText(context, "Static composable is clicked", Toast.LENGTH_SHORT)
                        .show()
                }
        )
    }

    Spacer(modifier = Modifier.height(40.dp))

    Row(modifier = Modifier.border(2.dp, Color.Red)) {
        Box(
            modifier = Modifier
                .graphicsLayer {
                    translationX = value
                }
                .clickable {
                    Toast
                        .makeText(context, "One with graphicsLayer is clicked", Toast.LENGTH_SHORT)
                        .show()
                }
                .zIndex(2f)
                .shadow(2.dp)
                .border(2.dp, Color.Green)
                .background(Orange400)
                .size(120.dp)
        )
        Box(
            modifier = Modifier
                .zIndex(1f)
                .background(Blue400)
                .size(120.dp)
                .clickable {
                    Toast
                        .makeText(context, "Static composable is clicked", Toast.LENGTH_SHORT)
                        .show()
                }
        )
    }

    Spacer(modifier = Modifier.height(5.dp))
    Text("Offset/Translation: ${value.round2Digits()}")
    Slider(
        value = value,
        onValueChange = {
            value = it
        },
        valueRange = 0f..1000f
    )

    Text(positionBeforeOffset)
    Text(positionAfterOffset)
}

可以看出,改变橙子组合的偏移不会影响蓝色组合的位置,但它会改变触摸位置的界限,并且在应用偏移之前和之后全局位置会改变

相关问题