android 在Jetpack合成中按百分比可合成的偏移

9njqaruj  于 2022-12-09  发布在  Android
关注(0)|答案(3)|浏览(170)

我只是想偏移图像总是准确的数额,无论什么屏幕分辨率的用户。
我这样试过:

var heightIs by remember { mutableStateOf(0f) }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .aspectRatio(
                ratio = 1f
            ).onGloballyPositioned { coordinates ->
                heightIs = (coordinates.size.height.toFloat())
            }
    ) {

        Image(
            painter = painterResource(id = R.drawable.base),
            contentDescription = "Shadow",
            modifier = Modifier.fillMaxSize()
        )
        Image(
            painter = painterResource(id = R.drawable.top_mask_normal),
            contentDescription = "Shadow Stencil",
            colorFilter = ColorFilter.tint(color, BlendMode.SrcAtop),
            modifier = Modifier
                .fillMaxSize()
                .offset(y = ((heightIs * 0.03).toInt()).dp)
        )
}

但我在不同的屏幕分辨率下得到不同的结果。我希望它完全每次都在同一位置,无论用户使用平板电脑还是480x800设备

ars1skjm

ars1skjm1#

使用heightIs * 0.03).toInt()).dp这一行,您不会转换成dp或密度无关像素。您会在像素值的末尾添加.dp扩展名。
要转换为dp,您需要使用LocalDensity.current.run{heightIs * 0.03).toInt().toDp()}
dp是以像素/密度计算的。如果您的设备密度为2.0,100 px应该是50.dp,但使用您现有的函数,您只需将100px更改为100.dp

nszi6y05

nszi6y052#

.dp只返回一个Dp类型的对象。您希望确保Composable以固定的“距离”移动,而不管屏幕的密度如何,但像素的大小是可变的。您需要某种转换机制,将您的像素值转换为在他们的设备上与在您的不同密度的设备上相等的距离。因此,您需要根据您的首选距离在您的设备上设置该值(例如,以像素为单位);那么你需要把你设备上的值**转换成一个Dp值。然后,你从转换中得到的值可以在任何地方使用,在任何设备上,原则上它会返回相同的“长度”。
假设您需要一个Dp,即设备上500个像素的密度无关像素值。

{ // ComposableScope
  val dips = with(LocalDensity.current) { pixels.toDp() }
}

现在,这个值只是用来获取转换为DP的像素值。记录这个值,或者通过调试器获取它,或者在屏幕上打印它,或者使用你想要的任何方法来获取这个值。一旦这个值在你手中,你就不再需要这个代码了。只要用获取的值初始化dips变量,它就可以在每个设备上正常工作(原则上)。
也在Doctor Thracian's answer处取一取。

ttvkxqim

ttvkxqim3#

heightIs的问题是,当在onGloballyPositioned中更新时,会导致重新组合。
Compose提供了布局修饰符来解决该问题。
这样的东西就可以工作,而不必使用状态

Box(
    modifier = Modifier
        .fillMaxSize()
        .aspectRatio(
            ratio = 1f
        )
) {

    Image(
        painter = painterResource(id = R.drawable.base),
        contentDescription = "Shadow",
        modifier = Modifier.fillMaxSize()
    )
    Image(
        painter = painterResource(id = R.drawable.top_mask_normal),
        contentDescription = "Shadow Stencil",
        colorFilter = ColorFilter.tint(color, BlendMode.SrcAtop),
        modifier = Modifier
            .fillMaxSize()
            .layout { measurable, constraint ->
                val placeable = measurable.measure(constraint)

                layout(constraint.width, constraint.height) {
                    placeable.placeRelative(
                        x = 0, 
                        y = (constraint.height * 0.03).toInt()
                    )
                }
            }
    )
}

相关问题