将布局子元素放在父元素边界外,同时保持高度。

huangapple go评论94阅读模式
英文:

Compose layout child outside parent bounds while maintaining height

问题

我试图使子Box在其高度较大且以某种方式对齐时扩展到父Box之外,因为子框底部对齐,所以我希望在父框内时不可见Cyan线。

但实际上会发生这种情况。

子框高度调整并打印为大约20.dp。

是否有可以利用以实现此效果的Modifier

val density = LocalDensity.current

Box(modifier = Modifier
    .padding(top = 250.dp)
    .fillMaxWidth()
    .height(20.dp)
    .background(Color.Red)
    .clipToBounds()
) {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(80.dp)
            .background(Color.Green)
            .align(Alignment.BottomCenter)
            .onSizeChanged {
                density.run {
                    Log.i("Box Height", it.height.toDp().toString())
                }
            }
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(5.dp)
                .background(Color.Cyan)
                .align(Alignment.TopCenter)
        )
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(5.dp)
                .background(Color.Yellow)
                .align(Alignment.BottomCenter)
        )
        Box(
            modifier = Modifier
                .fillMaxHeight()
                .width(5.dp)
                .background(Color.Magenta)
                .align(Alignment.CenterStart)
        )
        Box(
            modifier = Modifier
                .fillMaxHeight()
                .width(5.dp)
                .background(Color.Blue)
                .align(Alignment.CenterEnd)
        )
    }
}

将布局子元素放在父元素边界外,同时保持高度。

将布局子元素放在父元素边界外,同时保持高度。

英文:

I'm trying to get a child Box to extend outside parent Box when it's height is greater and it's aligned in a certain way. Because the child box is aligned bottom, I'd expect the Cyan line to not be visible when inside the parent box

将布局子元素放在父元素边界外,同时保持高度。

But instead this happens

将布局子元素放在父元素边界外,同时保持高度。

Child Box height resizes and prints out as being roughly 20.dp.

Is there a Modifier I can leverage to achieve this effect?

val density = LocalDensity.current

Box(modifier = Modifier
    .padding(top = 250.dp)
    .fillMaxWidth()
    .height(20.dp)
    .background(Color.Red)
    .clipToBounds()
) {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(80.dp)
            .background(Color.Green)
            .align(Alignment.BottomCenter)
            .onSizeChanged {
                density.run {
                    Log.i("Box Height", it.height.toDp().toString())
                }
            }
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(5.dp)
                .background(Color.Cyan)
                .align(Alignment.TopCenter)
        )
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(5.dp)
                .background(Color.Yellow)
                .align(Alignment.BottomCenter)
        )
        Box(
            modifier = Modifier
                .fillMaxHeight()
                .width(5.dp)
                .background(Color.Magenta)
                .align(Alignment.CenterStart)
        )
        Box(
            modifier = Modifier
                .fillMaxHeight()
                .width(5.dp)
                .background(Color.Blue)
                .align(Alignment.CenterEnd)
        )
    }
}

答案1

得分: 1

在Jetpack Compose中,您无法通过增加内容大小来增加父级大小。使用默认的Composables,甚至无法测量超出父级最小-最大宽度/高度约束范围之外的内容内的Composables。

Modifier.height(20.dp) 返回 minHeight =20.dp,max=20.dp,因此父级始终以20.dp高度测量。

但是,Modifier.wrapContentX(unbounded, align)Modifier.requiredX() 修饰符可以更改内容的 Constraints 最小-最大范围。

modifier = Modifier
    .fillMaxWidth()
    .wrapContentHeight(unbounded = true, align = Alignment.Bottom)
    .height(80.dp)
    .background(Color.Green)

将允许带有绿色背景的Box以80.dp进行测量,并通过底部对齐可以获得预期的结果。

wrapContent的定义如下:

允许内容以其所需的高度进行测量,而不考虑传入的测量最小高度约束,如果unbounded为true,也不考虑传入的测量最大高度约束。如果内容的测量大小小于最小高度约束,则将其与该最小高度空间对齐。如果内容的测量大小大于最大高度约束(仅在unbounded为true时可能),则在最大高度空间上对齐。

我用带有Constraints的Box替换了带有绿色背景的Box,这样您可以查看其中的Constraints,如果替换父级,您还可以查看来自父级的Constraints。

在上面的代码中,BoxWithConstraints 是一个用于显示Constraints的Composable,它会打印出红色Box和绿色Box的最小高度和最大高度。

此外,您的代码中包含了一个 @Preview@Composable 的示例函数 Test(),该函数在一个Column中包含了上述的BoxWithConstraints和其他Composables。

希望这有助于您理解Jetpack Compose中的布局和Constraints。

英文:

In Jetpack Compose you cannot increase parent size by increasing content size.
With default Composables it's not even possible to measure Composables inside content out of range of min-max width/height of Constraints from parent.

Modifier.height(20.dp) returns minHeight =20.dp, max=20.dp so parent is always measured with 20.dp height.

However Modifier.wrapContentX(unBounded, align) or Modifier.requiredX() modifiers can change Constraints min-max range for content.

modifier = Modifier
    .fillMaxWidth()
    .wrapContentHeight(unbounded = true, align = Alignment.Bottom)
    .height(80.dp)
    .background(Color.Green)

will let Box with green background to be measured with 80.dp and by aligning bottom you will be able get expected result.

wrapContent definition is as

> Allow the content to measure at its desired height without regard for
> the incoming measurement minimum height constraint, and, if unbounded
> is true, also without regard for the incoming measurement maximum
> height constraint. If the content's measured size is smaller than the
> minimum height constraint, align it within that minimum height space.
> If the content's measured size is larger than the maximum height
> constraint (only possible when unbounded is true), align over the
> maximum height space.

I replaced Box with green background with BoxWithConstraints so you can check out Constraints inside it, if you replace parent you can also constraints coming from it too.

将布局子元素放在父元素边界外,同时保持高度。

@Preview
@Composable
fun Test() {

    Column(Modifier.fillMaxSize()) {

        BoxWithConstraints(
            modifier = Modifier
                .padding(top = 250.dp)
                .fillMaxWidth()
                .height(20.dp)
                .background(Color.Red)
                .clipToBounds()
        ) {

            println("Red Box minHeight: $minHeight, maxHeight: $maxHeight")

            BoxWithConstraints(
modifier = Modifier
    .fillMaxWidth()
    .wrapContentHeight(unbounded = true, align = Alignment.Bottom)
    .height(80.dp)
    .background(Color.Green)

            ) {

                println("Green Box minHeight: $minHeight, maxHeight: $maxHeight")

                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(5.dp)
                        .background(Color.Cyan)
                        .align(Alignment.TopCenter)
                )
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(5.dp)
                        .background(Color.Yellow)
                        .align(Alignment.BottomCenter)
                )
                Box(
                    modifier = Modifier
                        .fillMaxHeight()
                        .width(5.dp)
                        .background(Color.Magenta)
                        .align(Alignment.CenterStart)
                )
                Box(
                    modifier = Modifier
                        .fillMaxHeight()
                        .width(5.dp)
                        .background(Color.Blue)
                        .align(Alignment.CenterEnd)
                )
            }
        }
    }
}

答案2

得分: 1

我找到了一个将 requiredHeightoffset y 结合的解决方案。我认为它也需要偏移量,因为在添加了 requiredHeight 后,Modifier.align(Alignment.BottomCenter) 会失效。

val parentHeight = 20.dp
val childHeight = 80.dp
val offsetY = (parentHeight - childHeight) / 2

Box(modifier = Modifier
    .padding(top = 250.dp)
    .fillMaxWidth()
    .height(parentHeight)
    .background(Color.Red)
    .clipToBounds()
) {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .requiredHeight(childHeight)
            .offset(y = offsetY)
            .background(Color.Green)
            .align(Alignment.BottomCenter)
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(5.dp)
                .background(Color.Cyan)
                .align(Alignment.TopCenter)
        )
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(5.dp)
                .background(Color.Yellow)
                .align(Alignment.BottomCenter)
        )
        Box(
            modifier = Modifier
                .fillMaxHeight()
                .width(5.dp)
                .background(Color.Magenta)
                .align(Alignment.CenterStart)
        )
        Box(
            modifier = Modifier
                .fillMaxHeight()
                .width(5.dp)
                .background(Color.Blue)
                .align(Alignment.CenterEnd)
        )
    }
}
英文:

I found a solution combining requiredHeight with offset y. It needs the offset too I think because Modifier.align(Alignment.BottomCenter) breaks after requiredHeight is added.

将布局子元素放在父元素边界外,同时保持高度。

val parentHeight = 20.dp
val childHeight = 80.dp
val offsetY = (parentHeight - childHeight) / 2

Box(modifier = Modifier
    .padding(top = 250.dp)
    .fillMaxWidth()
    .height(parentHeight)
    .background(Color.Red)
    .clipToBounds()
) {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .requiredHeight(childHeight)
            .offset(y = offsetY)
            .background(Color.Green)
            .align(Alignment.BottomCenter)
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(5.dp)
                .background(Color.Cyan)
                .align(Alignment.TopCenter)
        )
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(5.dp)
                .background(Color.Yellow)
                .align(Alignment.BottomCenter)
        )
        Box(
            modifier = Modifier
                .fillMaxHeight()
                .width(5.dp)
                .background(Color.Magenta)
                .align(Alignment.CenterStart)
        )
        Box(
            modifier = Modifier
                .fillMaxHeight()
                .width(5.dp)
                .background(Color.Blue)
                .align(Alignment.CenterEnd)
        )
    }
}

huangapple
  • 本文由 发表于 2023年8月11日 03:14:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76878720.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定