【问题标题】:Offset Composable by percentage in Jetpack Compose在 Jetpack Compose 中按百分比偏移 Composable
【发布时间】:2022-12-08 03:34:49
【问题描述】:

我只是想始终偏移图像的确切数量,而不管用户的屏幕分辨率如何。

我这样试过:

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 设备,每次都在同一位置

【问题讨论】:

  • 您希望偏移量表示每个屏幕分辨率的相同距离,但您是根据屏幕高度计算偏移量?先生,你到底认为你在这里做什么?

标签: android kotlin android-jetpack-compose android-jetpack


【解决方案1】:

使用此行,heightIs * 0.03).toInt()).dp,您不会转换为 dp 或密度独立像素。您正在将 .dp 扩展名添加到像素值的末尾。

要转换为 dp,您需要使用 LocalDensity.current.run{heightIs * 0.03).toInt().toDp()}

dp 计算为像素/密度。如果你的设备有 2.0 密度 100px 应该是 50.dp 但你现有的功能你只需将 100px 更改为 100.dp

【讨论】:

  • Thrace 博士,这个问题很矛盾。 OP 需要准确的距离(如以厘米为单位)对于应用程序运行的所有设备都是相同的,但仍在使用设备的特定高度计算它。他想在没有降落伞的情况下从空间站跳下,但仍想活下来。不过你的回答很有帮助
  • 另外,OP,考虑在将答案标记为正确的同时对答案进行投票。这是一种感激之情,当提问者的问题得到解决时,这是传统上期望的。
  • @RichardOnslowRoper 我不认为这是自相矛盾的。 OP 希望 Composable 的位置在所有设备上都处于相同的百分比。这是我在 Canvas 中使用的一种方法,使线条或形状与屏幕宽度或高度相对应,以便在任何视图或可组合尺寸中具有相似的外观,就像 this link 中的这个指南针一样。 OP 唯一遗漏的是转换为 dp,这可能会造成混淆。我记得另一个类似的问题试图通过将 dp 添加到像素值的末尾来转换为 dp
  • 我的意思是他从来没有提到过百分.事实上,他提到“确切的数量”和“我想要它确切地同时位置每次用户使用平板电脑还是 480x800 设备都无所谓”。这些显然与偏移量取决于高度这一事实相冲突。你怎么能让 400x800px 设备的 20% 高度与 20% 的设备相同400x1000px?在数学上不合逻辑且毫无意义。
  • THAT 是个罗盘人!
【解决方案2】:

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

假设您想要一个 Dp,即设备上 500 像素的密度无关像素值。转换过程是

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

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

也可以在Doctor Thracian's answer 上拍摄。

【讨论】:

    【解决方案3】:

    heightIs的问题是在onGlobalPositioned中更新时会引起重组。

    Compose 提供了 layout 修饰符来解决这个问题。

    这样的东西可以工作,而不必使用状态

    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()
                        )
                    }
                }
        )
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-25
      • 2023-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      • 2021-02-19
      • 1970-01-01
      相关资源
      最近更新 更多