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

Oja*_*jav 1 android kotlin android-jetpack-compose

我尝试在他使用的地方使用这个答案OnGloballyPositionedModifier,但它没有返回我孩子的正确绝对 Pos。我尝试过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)
                        )
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

打印以下内容

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????
Run Code Online (Sandbox Code Playgroud)

有没有办法获得我的可组合函数相对于整个 ANDROID WINDOW 的绝对位置?

编辑1:

@Composable
fun PixelToDp(pixelSize: Int): Dp {
    return with(LocalDensity.current) { pixelSize.toDp() }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

编辑: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)
    )

Run Code Online (Sandbox Code Playgroud)

印刷

I/System.out:  Size 2: 150 x 150
I/System.out:  Size 1: 150 x 150
Run Code Online (Sandbox Code Playgroud)

Thr*_*ian 9

当您检查可组合项的位置时,您没有考虑修饰符的顺序

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)
)
Run Code Online (Sandbox Code Playgroud)

印刷:

 POSITION 1: Offset(0.0, 0.0)
 POSITION 2: Offset(100.0, 50.0)
Run Code Online (Sandbox Code Playgroud)

在这个答案中,我解释了修饰符的顺序如何改变某些修饰符(包括 Modifier.offset)的结果

/sf/answers/5190174321/

我制作了一个示例来显示与兄弟姐妹、其他修改器和基于如何再次应用修改器的位置的交互 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)
}
Run Code Online (Sandbox Code Playgroud)

可以看出,更改橙色可组合项的偏移量不会影响蓝色可组合项的位置,但它会更改触摸位置的边界位置以及应用偏移量之前和之后全局位置的变化

在此输入图像描述