Android Jetpack Compose 宽度/高度/大小修饰符 vs requiredWidth/requiredHeight/requiredSize

Val*_*kov 3 android android-layout android-jetpack android-jetpack-compose

Android Jetpack Compose 包含width(),height()size()布局修饰符以及requiredWidth(),requiredHeight()requiredSize()。这两组修饰符有什么区别?我应该使用普通修饰符还是必需的修饰符?

Thr*_*ian 23

在 jetpack Compose 中,可组合项或子可组合项的尺寸是使用约束来设置的,约束是一组尺寸和有界或有限的标志。Modifier.requiredX用于扩大约束或强制新的约束,但如果约束不在父级的限制中,则很容易破坏布局。

\n
/**\n * Create a [Constraints]. [minWidth] and [minHeight] must be positive and\n * [maxWidth] and [maxHeight] must be greater than or equal to [minWidth] and [minHeight],\n * respectively, or [Infinity][Constraints.Infinity].\n */\n@Stable\nfun Constraints(\n    minWidth: Int = 0,\n    maxWidth: Int = Constraints.Infinity,\n    minHeight: Int = 0,\n    maxHeight: Int = Constraints.Infinity\n): Constraints {\n    require(maxWidth >= minWidth) {\n        "maxWidth($maxWidth) must be >= than minWidth($minWidth)"\n    }\n    require(maxHeight >= minHeight) {\n        "maxHeight($maxHeight) must be >= than minHeight($minHeight)"\n    }\n    require(minWidth >= 0 && minHeight >= 0) {\n        "minWidth($minWidth) and minHeight($minHeight) must be >= 0"\n    }\n    return Constraints.createConstraints(minWidth, maxWidth, minHeight, maxHeight)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

基于Constraints测量期间的宽度和高度被分配给可组合项作为Placeables。大小修饰符在返回的测量函数内执行MeasureResult

\n
    val placeable = measurable.measure(wrappedConstraints)\n    return layout(placeable.width, placeable.height) {\n        placeable.placeRelative(0, 0)\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

当我们分配任何大小修饰符时,我们实际上并没有分配我们传递的大小Constraints,而是根据Constraints可组合的最小-最大属性​​的范围在内部进行测量MeasureScope并放置在PlacementScopelayout()函数内部。

\n

例如,在密度为 1.0 的设备上 Modifier.size(50.dp) 通过Constraints(minWidth = 50, maxWidth = 50, minHeight = 50, maxHewight= 50)。我们设置了一个固定范围Constraints来测量我们的可组合项,它只能有 50.dp 大小。

\n

如果我们设置一个范围,Modifier.sizeIn例如Modifier.sizeIn(minWidth=50, maxWidth=100, minHeight=50, maxHeight=100)Composable 可以在 50.dp 和 100.dp 之间,因为我们分配了一个开放范围的约束。

\n

当我们分配时,Modifier.size(50.dp).size(100.dp)我们将\n传递Constraint(50, 50, 50, 50)给具有目标约束的第二个大小修饰符Constraints(100, 100, 100, 100)

\n

Modifier.size/width/height/sizeIn/widthIn/heightInModifier.requiredSize/SizeIn/width/WidthIn/HeightIn修饰符共享相同的源代码,但有细微差别,size修饰符检查

\n
/**\n * Takes [otherConstraints] and returns the result of coercing them in the current constraints.\n * Note this means that any size satisfying the resulting constraints will satisfy the current\n * constraints, but they might not satisfy the [otherConstraints] when the two set of constraints\n * are disjoint.\n * Examples (showing only width, height works the same):\n * (minWidth=2, maxWidth=10).constrain(minWidth=7, maxWidth=12) -> (minWidth = 7, maxWidth = 10)\n * (minWidth=2, maxWidth=10).constrain(minWidth=11, maxWidth=12) -> (minWidth=10, maxWidth=10)\n * (minWidth=2, maxWidth=10).constrain(minWidth=5, maxWidth=7) -> (minWidth=5, maxWidth=7)\n */\nfun Constraints.constrain(otherConstraints: Constraints) = Constraints(\n    minWidth = otherConstraints.minWidth.coerceIn(minWidth, maxWidth),\n    maxWidth = otherConstraints.maxWidth.coerceIn(minWidth, maxWidth),\n    minHeight = otherConstraints.minHeight.coerceIn(minHeight, maxHeight),\n    maxHeight = otherConstraints.maxHeight.coerceIn(minHeight, maxHeight)\n)\n
Run Code Online (Sandbox Code Playgroud)\n

Modifier.size/width/height/sizeIn/widthIn/heightIn修饰符分配上,此检查已完成,但为了简单起见,我将解释链中的第二个大小Modifier.size(50.dp).size(100.dp)

\n

这里分配了 100.dp 的约束otherConstraints,min\n和 max 来自当前大小,在我们的例子中Modifier.size(50.dp),结果100.coerceIn(50, 50)返回 50,这就是使用第一个的原因。

\n
If we chain Modifier.widthIn(50.dp, 100.dp).width(80.dp) it returns 80.dp\n\nIf we chain Modifier.widthIn(50.dp, 100.dp).width(120.dp) it returns 100.dp\n\nIf we chain Modifier.widthIn(50.dp, 100.dp).width(40.dp) returns 50.dp\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n
@Composable\nprivate fun ChainSizeModifiersSample() {\n    TutorialText2(text = "\xe2\x9d\x8cfillMaxWidth().width(50.dp)")\n\n    BoxWithConstraints(\n        modifier = Modifier\n            .fillMaxWidth()\n            .width(50.dp)\n            .border(2.dp, Color.Red)\n    ) {\n        Text(text = "minWidth: $minWidth, maxWidth: $maxWidth")\n    }\n\n    TutorialText2(text = "\xe2\x9d\x8cwidth(200).width(50.dp)")\n    BoxWithConstraints(\n        modifier = Modifier\n            .width(200.dp)\n            .width(50.dp)\n            .border(2.dp, Color.Red)\n    ) {\n        Text(text = "minWidth: $minWidth, maxWidth: $maxWidth")\n    }\n\n    StyleableTutorialText(\n        text = "2-) **Modifier.width/height/sizeIn** describes a range " +\n                "between min and max values. It\'s allowed to narrow range but " +\n                "not allowed to widen it as can be seen examples below."\n    )\n\n    TutorialText2(text = "\xe2\x9c\x85widthIn(min = 100.dp, max = 200.dp).width(150.dp)")\n    BoxWithConstraints(\n        modifier = Modifier\n            .widthIn(min = 100.dp, max = 200.dp)\n            .width(150.dp)\n            .border(2.dp, Color.Green)\n    ) {\n        Text(text = "minWidth: $minWidth, maxWidth: $maxWidth")\n    }\n\n    TutorialText2(text = "\xe2\x9d\x8cwidthIn(min = 100.dp, max = 200.dp).width(50.dp)")\n    BoxWithConstraints(\n        modifier = Modifier\n            .widthIn(min = 100.dp, max = 200.dp)\n            .width(50.dp)\n            .border(2.dp, Color.Red)\n    ) {\n        Text(text = "minWidth: $minWidth, maxWidth: $maxWidth")\n    }\n\n    TutorialText2(text = "\xe2\x9d\x8cwidthIn(min = 100.dp, max = 200.dp).width(250.dp)")\n    BoxWithConstraints(\n        modifier = Modifier\n            .widthIn(min = 100.dp, max = 200.dp)\n            .width(250.dp)\n            .border(2.dp, Color.Red)\n    ) {\n        Text(text = "minWidth: $minWidth, maxWidth: $maxWidth")\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

即使requiredX修饰符共享相同的代码,它在返回时也有细微的Constraints差别

\n
        val resolvedMinWidth = if (minWidth != Dp.Unspecified) {\n            targetConstraints.minWidth\n        } else {\n            constraints.minWidth.coerceAtMost(targetConstraints.maxWidth)\n        }\n        val resolvedMaxWidth = if (maxWidth != Dp.Unspecified) {\n            targetConstraints.maxWidth\n        } else {\n            constraints.maxWidth.coerceAtLeast(targetConstraints.minWidth)\n        }\n        val resolvedMinHeight = if (minHeight != Dp.Unspecified) {\n            targetConstraints.minHeight\n        } else {\n            constraints.minHeight.coerceAtMost(targetConstraints.maxHeight)\n        }\n        val resolvedMaxHeight = if (maxHeight != Dp.Unspecified) {\n            targetConstraints.maxHeight\n        } else {\n            constraints.maxHeight.coerceAtLeast(targetConstraints.minHeight)\n        }\n
Run Code Online (Sandbox Code Playgroud)\n

如果您注意源代码大小修饰符只能缩小约束范围,但requiredX修饰符也可以扩大它,基本上它们没有限制,例如size/width/height/sizeIn/widthIn/heightIn可以在当前约束之后设置任何目标约束。

\n

Modifier.width(50.dp).requiredWidh(100.dp)将最小和最大 50.dp 更改为 100.dp,其中您的可组合项可以使用最小-最大 100.dp 进行测量,因此它会被分配 100.dp 宽度。

\n

但是,如果不遵守父项或初始项的约束,则父项会将此视为 50.dp,它会尝试将内容居中,并根据requiredX修改器大于或小于初始size修改器的大小将该子项向左或向右推。

\n

在此输入图像描述

\n
@Composable\nprivate fun ChainRequiredSizeModifierSample() {\n    // In these examples requiredWidth constraints do not match the one comes from Modifier.size\n    // Because of that parent attempts to place them in center. When required is bigger\n    // it\'s placed at (parent.max-max) at left side. When required is smaller content is\n    // place at right side(centered in parent).\n    Column(\n        modifier = Modifier\n            .fillMaxWidth()\n            .padding(20.dp)\n            .border(2.dp, Blue400)\n    ) {\n        TutorialText2(text = "\xe2\x9d\x8csize(100.dp).requiredWidth(140.dp)")\n        BoxWithConstraints(\n            modifier = Modifier\n                .border(2.dp, Color.Red)\n                .size(100.dp)\n                .requiredWidth(140.dp)\n        ) {\n            Text(\n                text = "minWidth: $minWidth, maxWidth: $maxWidth",\n                modifier = Modifier.border(3.dp, Color.Green)\n            )\n        }\n\n        TutorialText2(text = "\xe2\x9d\x8csize(100.dp).requiredWidth(80.dp)")\n        BoxWithConstraints(\n            modifier = Modifier\n                .border(2.dp, Color.Red)\n                .size(100.dp)\n                .requiredWidth(80.dp)\n        ) {\n            Text(\n                text = "minWidth: $minWidth, maxWidth: $maxWidth",\n                modifier = Modifier.border(3.dp, Color.Green)\n            )\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

代码可以在这里找到

\n

何时使用 Modifier.requiredX

\n

通常,Modifier.requiredX当您希望强制使用最小尺寸时,会使用变体,但您也可以使用它来强制最大尺寸。CheckBox 使用它强制 20.dp 大小

\n
Canvas(modifier.wrapContentSize(Alignment.Center).requiredSize(CheckboxSize))\n
Run Code Online (Sandbox Code Playgroud)\n

如果您分配的大小修饰符小于 20.dp,您会发现它没有放置在应有的位置。滑块也同样如此

\n
   BoxWithConstraints(\n        modifier\n            .minimumInteractiveComponentSize()\n            .requiredSizeIn(minWidth = ThumbRadius * 2, minHeight = ThumbRadius * 2)\n
Run Code Online (Sandbox Code Playgroud)\n

它们需要具有最小尺寸才能正确显示或绘制。如果我们分配的大小不是必需的,它会尝试居中,如上面的示例所示。

\n

在此输入图像描述

\n
@Preview\n@Composable\nprivate fun RequiredSample() {\n    Column(\n        modifier = Modifier.fillMaxSize().padding(20.dp).border(2.dp, Color.Cyan)\n    ) {\n        Checkbox(checked = true, onCheckedChange = null, modifier = Modifier.size(20.dp))\n        Spacer(Modifier.height(30.dp))\n        Checkbox(checked = true, onCheckedChange = null, modifier = Modifier.size(10.dp))\n        Spacer(Modifier.height(30.dp))\n        Slider(\n            value = 0f,\n            onValueChange = {},\n            modifier = Modifier.size(48.dp).border(2.dp, Color.Green)\n        )\n        Spacer(Modifier.height(30.dp))\n        Slider(\n            value = 0f,\n            onValueChange = {},\n            modifier = Modifier.size(20.dp).border(2.dp, Color.Green)\n        )\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

尺寸调节剂

\n

Modifier.width/height()

\n

返回固定约束或具有相等 minWidth/Height 和 maxWidth/Height 的约束。\n因此子可组合项仅限于此约束

\n

Modifier.fillmaxWidth/Height(分数)

\n

覆盖父级最大约束下可用的空间部分。它返回父宽度/高度作为最小和最大宽度/高度

\n

Modifier.width/heightIn(min)

\n

将最小宽度/高度保留为此值,以便可以使用此尺寸来测量子可组合项。子项可以低于此值或更大,直到最大宽度/高度

\n

Modifier.width/heightIn(最大)

\n

这是可以测量儿童的最大宽度/高度。子可组合项的测量尺寸不能大于最大宽度/高度。

\n\n
@Composable\nprivate fun ConstraintsSample1() {\n    Text(text = "Fixed Size")\n    BoxWithConstraints(modifier = Modifier\n        .size(100.dp)\n        .border(3.dp, Color.Green)) {\n        Box(modifier = Modifier\n            .size(50.dp)\n            .background(Color.Red))\n    }\n\n    Spacer(modifier=Modifier.height(10.dp))\n    BoxWithConstraints(modifier = Modifier\n        .size(100.dp)\n        .border(3.dp, Color.Green)) {\n        Box(modifier = Modifier\n            .size(150.dp)\n            .background(Color.Red))\n    }\n\n    Text(text = "widthIn(min)")\n\n    BoxWithConstraints(modifier = Modifier\n        .widthIn(min = 100.dp)\n        .border(3.dp, Color.Green)) {\n        Box(modifier = Modifier\n            .size(50.dp)\n            .background(Color.Red))\n    }\n\n    Spacer(modifier=Modifier.height(10.dp))\n    BoxWithConstraints(modifier = Modifier\n        .widthIn(min = 100.dp)\n        .border(3.dp, Color.Green)) {\n        Box(modifier = Modifier\n            .size(150.dp)\n            .background(Color.Red))\n    }\n\n\n    Text(text = "widthIn(max)")\n\n    BoxWithConstraints(modifier = Modifier\n        .widthIn(max = 100.dp)\n        .border(3.dp, Color.Green)) {\n        Box(modifier = Modifier\n            .size(50.dp)\n            .background(Color.Red))\n    }\n\n    Spacer(modifier=Modifier.height(10.dp))\n    BoxWithConstraints(modifier = Modifier\n        .widthIn(max = 100.dp)\n        .border(3.dp, Color.Green)) {\n        Box(modifier = Modifier\n            .size(150.dp)\n            .background(Color.Red))\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Modifier.requiredWidth/Height()

\n将内容的宽度/高度限制在 `minDp` 和 `maxDp` 之间。如果内容选择的大小不满足传入的 Constraints,则父布局将报告为 Constraints 中强制的大小,并且内容的位置将自动偏移以以父级分配给子级的空间为中心在尊重约束的假设下进行布局。\n

例如,当您设置Modifier.size(50.dp).size(100.dp)第一个尺寸修饰符时,但是如果您用户 requiredIn

\n
Modifier.size(50.dp).requiredSize(100.dp) \n
Run Code Online (Sandbox Code Playgroud)\n

100.dp 但布局放置为两个维度之间差异的一半

\n\n
@Composable\nprivate fun ConstraintsSample2() {\n\n    Column(modifier = Modifier\n        .fillMaxSize()\n        .padding(30.dp)\n        .border(4.dp, Color.Cyan)) {\n\n        Text(text = "Chaining size modifiers")\n\n        Box(modifier = Modifier\n            .size(50.dp)\n            .background(Color.Yellow))\n\n        Box(modifier = Modifier\n            .size(50.dp)\n            .size(100.dp)\n            .background(Color.Red))\n\n        Box(modifier = Modifier\n            .size(50.dp)\n            .requiredSizeIn(100.dp)\n            .background(Color.Green))\n\n\n        Text(text = "widthIn(max)")\n\n        BoxWithConstraints(\n            modifier = Modifier\n                .width(100.dp)\n                .border(3.dp, Color.Green)\n        ) {\n            Box(\n                modifier = Modifier\n                    .requiredWidthIn(min = 20.dp, max = 50.dp)\n                    .height(50.dp)\n                    .background(Color.Red)\n            )\n        }\n\n        Spacer(modifier = Modifier.height(10.dp))\n        BoxWithConstraints(\n            modifier = Modifier\n                .width(100.dp)\n                .border(3.dp, Color.Green)\n        ) {\n            Box(\n                modifier = Modifier\n                    .requiredWidthIn(min = 150.dp, max = 200.dp)\n                    .height(50.dp)\n                    .background(Color.Red)\n            )\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在下面的示例中,当 TextField 没有固定大小的父级时,它会增长到最大宽度。如果使用 Modifier.widthIn() 时设置了小于 TextField 的固定大小,则 TextField 设置为父宽度,而 Modifier.requiredWidthIn() 跳出父级为 (TextField 大小 - 父级大小)/2

\n

在此输入图像描述

\n
@Composable\nprivate fun TextFieldSamples() {\n\n    Column(\n        modifier = Modifier\n            .padding(20.dp).border(2.dp, Color.Cyan)\n    ) {\n\n        var text1 by remember { mutableStateOf("") }\n\n        Column(modifier = Modifier) {\n            TextField(\n                modifier = Modifier\n                    .border(2.dp, Color.Green)\n                    .widthIn(56.dp),\n                value = text1,\n                onValueChange = { text1 = it }\n            )\n\n            TextField(\n                modifier = Modifier\n                    .border(2.dp, Color.Red)\n                    .requiredWidth(56.dp),\n                value = text1, onValueChange = { text1 = it })\n        }\n\n        Spacer(modifier = Modifier.height(30.dp))\n\n        var text2 by remember { mutableStateOf("") }\n\n        Column(modifier = Modifier.width(50.dp)) {\n            TextField(\n                modifier = Modifier\n                    .border(2.dp, Color.Green)\n                    .widthIn(56.dp),\n                value = text2, onValueChange = { text2 = it })\n\n            TextField(\n                modifier = Modifier\n                    .border(2.dp, Color.Red)\n                    .requiredWidth(56.dp),\n                value = text2, onValueChange = { text2 = it })\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

约束条件

\n

约束根据尺寸修改器、垂直/水平滚动或父级选择限制或想要使用最小或最大尺寸的方式而变化。

\n

我的设备上的最大设备宽度为 1080px,在下面的示例中 200.dp 为 525px。并使用了verticalScroll,这就是为什么高度是用Constraints.Infinity

\n\n
@Composable\nfun ConstraintsSample3() {\n    Column(modifier = Modifier) {\n\n        Text(text = "No Dimension Modifier")\n\n        BoxWithConstraints(modifier = Modifier.background(Brown400)) {\n            val hasBoundedWidth = constraints.hasBoundedWidth\n            val hasFixedWidth = constraints.hasFixedWidth\n            val minWidth = constraints.minWidth\n            val maxWidth = constraints.maxWidth\n\n            val hasBoundedHeight = constraints.hasBoundedHeight\n            val hasFixedHeight = constraints.hasFixedHeight\n            val minHeight = constraints.minHeight\n            val maxHeight = constraints.maxHeight\n            Text(\n                "minWidth: $minWidth, maxWidth: $maxWidth\\n" +\n                        "hasBoundedWidth: $hasBoundedWidth, hasFixedWidth: $hasFixedWidth\\n" +\n                        "minHeight: $minHeight, maxHeight: $maxHeight\\n" +\n                        "hasBoundedHeight: $hasBoundedHeight, hasFixedHeight: $hasFixedHeight",\n                color = Color.White\n            )\n        }\n\n        Spacer(modifier = Modifier.height(10.dp))\n        Text(text = "FillMaxWidth and 200.dp Height")\n        BoxWithConstraints(\n            modifier = Modifier\n                .fillMaxWidth()\n                .height(200.dp)\n                .background(Red400)\n        ) {\n            val hasBoundedWidth = constraints.hasBoundedWidth\n            val hasFixedWidth = constraints.hasFixedWidth\n            val minWidth = constraints.minWidth\n            val maxWidth = constraints.maxWidth\n\n            val hasBoundedHeight = constraints.hasBoundedHeight\n            val hasFixedHeight = constraints.hasFixedHeight\n            val minHeight = constraints.minHeight\n            val maxHeight = constraints.maxHeight\n            Text(\n                "minWidth: $minWidth, maxWidth: $maxWidth\\n" +\n                        "hasBoundedWidth: $hasBoundedWidth, hasFixedWidth: $hasFixedWidth\\n" +\n                        "minHeight: $minHeight, maxHeight: $maxHeight\\n" +\n                        "hasBoundedHeight: $hasBoundedHeight, hasFixedHeight: $hasFixedHeight",\n                color = Color.White\n            )\n        }\n\n        Spacer(modifier = Modifier.height(10.dp))\n        Text(text = "wrapContentSize()")\n        BoxWithConstraints(\n            modifier = Modifier\n                .wrapContentSize()\n                .background(Orange400)\n        ) {\n\n            val hasBoundedWidth = constraints.hasBoundedWidth\n            val hasFixedWidth = constraints.hasFixedWidth\n            val minWidth = constraints.minWidth\n            val maxWidth = constraints.maxWidth\n\n            val hasBoundedHeight = constraints.hasBoundedHeight\n            val hasFixedHeight = constraints.hasFixedHeight\n            val minHeight = constraints.minHeight\n            val maxHeight = constraints.maxHeight\n            Text(\n                "minWidth: $minWidth, maxWidth: $maxWidth\\n" +\n                        "hasBoundedWidth: $hasBoundedWidth\\n" +\n                        "hasFixedWidth: $hasFixedWidth\\n" +\n                        "minHeight: $minHeight\\n" +\n                        "maxHeight: $maxHeight\\n" +\n                        "hasBoundedHeight: $ha


Val*_*kov 12

不同的是,普通的像改性宽度()考虑到布局约束需要像改性剂requiredWidth()忽略它们。您可以将约束视为测量元素的最小/最大宽度/高度。为了更好地理解布局修饰符和约束是如何工作的,请查看这篇文章

让我们看一个宽度修饰符的例子,高度大小的行为方式相同。

@Composable
fun WidthModifierExample() {
    val columnWidth = 200.dp

    Column(
        modifier = Modifier
            .width(columnWidth)
            .border(1.dp, Color.Gray)
    ) {
        Text(
            text = "requiredWidth = parent - 50",
            modifier = Modifier
                .requiredWidth(columnWidth - 50.dp)
                .background(Color.LightGray)
        )
        Text(
            text = "requiredWidth = parent + 50",
            modifier = Modifier
                .requiredWidth(columnWidth + 50.dp)
                .background(Color.LightGray)
        )
        Text(
            text = "width = parent - 50",
            modifier = Modifier
                .width(columnWidth - 50.dp)
                .background(Color.LightGray),
        )
        Text(
            text = "width = parent + 50",
            modifier = Modifier
                .width(columnWidth + 50.dp)
                .background(Color.LightGray)
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

深灰色边框为列边界,文本背景为浅灰色。Modifier.width(200.dp)应用于列,因此它接收minWidth = 200dp; maxWidth = 200dp约束。该所以每个孩子得到的布局并不限制其孩子最小宽度minWidth = 0; maxWidth = 200dp的限制。前两个文本使用requiredWidth()修饰符忽略此约束,因此第二个文本比父列宽。最后一个文本宽度200dp根据maxWidth = 200dp约束减小,因为它使用width()修饰符代替。

在上面的示例中,仅限制了文本的最大宽度。让我们看另一个示例,其中最小宽度也受到限制:

@Composable
fun WidthModifierExample() {
    Column(
        modifier = Modifier.border(1.dp, Color.Gray)
    ) {
        val minWidth = 140
        val maxWidth = 200
        val widthDescriptions = arrayOf(
            WidthDescription(minWidth - 50, "min - 50"),
            WidthDescription((minWidth + maxWidth) / 2, "between min and max"),
            WidthDescription(maxWidth + 50, "max + 50")
        )

        for (widthDescription in widthDescriptions) {
            Text(
                text = "requiredWidth = ${widthDescription.description}",
                modifier = Modifier
                    .border(.5.dp, Color.Red)
                    .widthIn(minWidth.dp, maxWidth.dp)
                    .background(Color.LightGray)
                    .requiredWidth(widthDescription.width.dp)
            )
        }

        for (widthDescription in widthDescriptions) {
            Text(
                text = "width = ${widthDescription.description}",
                modifier = Modifier
                    .border(.5.dp, Color.Red)
                    .widthIn(minWidth.dp, maxWidth.dp)
                    .background(Color.LightGray)
                    .width(widthDescription.width.dp)
            )
        }
    }
}

data class WidthDescription(
    val width: Int,
    val description: String
)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

在这种情况下,Column()不添加任何约束,但每个子项Text()都包含在widthIn()修饰符中,该修饰符添加了自己的约束。浅灰色背景显示文本大小,而红色边框显示结果元素的尺寸。如您所见requiredWidth(),前三个文本的修饰符忽略了外部约束,因此元素宽度及其子元素Text()宽度可能不同。最后三个文本使用width()修饰符,它考虑了约束,因此Text()宽度始终与结果元素匹配。