在 jetpack Compose 中,可组合项或子可组合项的尺寸是使用约束来设置的,约束是一组尺寸和有界或有限的标志。并且 be Modifier.requiredX 用于强制大小,但如果约束不在父级的限制中,它很容易破坏您的布局。
之间的区别widthIn
and requiredWidthIn
是第一个遵守的之前的尺寸修饰符或最大父尺寸而后者可以力约束.
/**
* Create a [Constraints]. [minWidth] and [minHeight] must be positive and
* [maxWidth] and [maxHeight] must be greater than or equal to [minWidth] and [minHeight],
* respectively, or [Infinity][Constraints.Infinity].
*/
@Stable
fun Constraints(
minWidth: Int = 0,
maxWidth: Int = Constraints.Infinity,
minHeight: Int = 0,
maxHeight: Int = Constraints.Infinity
): Constraints {
require(maxWidth >= minWidth) {
"maxWidth($maxWidth) must be >= than minWidth($minWidth)"
}
require(maxHeight >= minHeight) {
"maxHeight($maxHeight) must be >= than minHeight($minHeight)"
}
require(minWidth >= 0 && minHeight >= 0) {
"minWidth($minWidth) and minHeight($minHeight) must be >= 0"
}
return Constraints.createConstraints(minWidth, maxWidth, minHeight, maxHeight)
}
基于Constraints
在测量期间,宽度和高度被分配给可组合项,如下所示Placeable
s.
在下面的示例中,当 TextField 没有固定大小的父级时,它会增长到最大宽度。如果使用 Modifier.widthIn() 时设置了小于 TextField 的固定大小,则 TextField 设置为父级宽度,而 Modifier.requiredWidthIn() 跳出父级为 (TextField 大小 - 父级大小)/2
@Composable
private fun TextFieldSamples() {
Column(
modifier = Modifier
.padding(20.dp).border(2.dp, Color.Cyan)
) {
var text1 by remember { mutableStateOf("") }
Column(modifier = Modifier) {
TextField(
modifier = Modifier
.border(2.dp, Color.Green)
.widthIn(56.dp),
value = text1,
onValueChange = { text1 = it }
)
TextField(
modifier = Modifier
.border(2.dp, Color.Red)
.requiredWidthIn(56.dp),
value = text1, onValueChange = { text1 = it })
}
Spacer(modifier = Modifier.height(30.dp))
var text2 by remember { mutableStateOf("") }
Column(modifier = Modifier.width(50.dp)) {
TextField(
modifier = Modifier
.border(2.dp, Color.Green)
.widthIn(56.dp),
value = text2, onValueChange = { text2 = it })
TextField(
modifier = Modifier
.border(2.dp, Color.Red)
.requiredWidthIn(56.dp),
value = text2, onValueChange = { text2 = it })
}
}
}
尺寸调节剂
Modifier.width/height()
返回固定约束或具有相等 minWidth/Height 和 maxWidth/Height 的约束。
所以子可组合项仅限于此约束
Modifier.fillmaxWidth/Height(分数)
覆盖父级最大约束下可用的空间的一部分
Modifier.width/heightIn(min)
将最小宽度/高度保留为此值,以便可以使用此尺寸来测量子可组合项。子项可以低于此值或更大,直到最大宽度/高度
Modifier.width/heightIn(最大)
这是可以测量儿童的最大宽度/高度。子可组合项的测量尺寸不能大于最大宽度/高度。
@Composable
private fun ConstraintsSample1() {
Text(text = "Fixed Size")
BoxWithConstraints(modifier = Modifier
.size(100.dp)
.border(3.dp, Color.Green)) {
Box(modifier = Modifier
.size(50.dp)
.background(Color.Red))
}
Spacer(modifier=Modifier.height(10.dp))
BoxWithConstraints(modifier = Modifier
.size(100.dp)
.border(3.dp, Color.Green)) {
Box(modifier = Modifier
.size(150.dp)
.background(Color.Red))
}
Text(text = "widthIn(min)")
BoxWithConstraints(modifier = Modifier
.widthIn(min = 100.dp)
.border(3.dp, Color.Green)) {
Box(modifier = Modifier
.size(50.dp)
.background(Color.Red))
}
Spacer(modifier=Modifier.height(10.dp))
BoxWithConstraints(modifier = Modifier
.widthIn(min = 100.dp)
.border(3.dp, Color.Green)) {
Box(modifier = Modifier
.size(150.dp)
.background(Color.Red))
}
Text(text = "widthIn(max)")
BoxWithConstraints(modifier = Modifier
.widthIn(max = 100.dp)
.border(3.dp, Color.Green)) {
Box(modifier = Modifier
.size(50.dp)
.background(Color.Red))
}
Spacer(modifier=Modifier.height(10.dp))
BoxWithConstraints(modifier = Modifier
.widthIn(max = 100.dp)
.border(3.dp, Color.Green)) {
Box(modifier = Modifier
.size(150.dp)
.background(Color.Red))
}
}
Modifier.requiredWidth/Height()
Constrain the width/height of the content to be between `minDp` and `maxDp`. If the content chooses a size that does not satisfy the incoming Constraints, the parent layout will be reported a size coerced in the Constraints, and the position of the content will be automatically offset to be centered on the space assigned to the child by the parent layout under the assumption that Constraints were respected.
例如当你设置Modifier.size(50.dp).size(100.dp)
但是,如果您用户需要,则应用第一个尺寸修饰符
Modifier.size(50.dp).requiredSizeIn(100.dp)
100.dp 是强制的,但布局放置为两个维度之间差异的一半
@Composable
private fun ConstraintsSample2() {
Column(modifier = Modifier
.fillMaxSize()
.padding(30.dp)
.border(4.dp, Color.Cyan)) {
Text(text = "Chaining size modifiers")
Box(modifier = Modifier
.size(50.dp)
.background(Color.Yellow))
Box(modifier = Modifier
.size(50.dp)
.size(100.dp)
.background(Color.Red))
Box(modifier = Modifier
.size(50.dp)
.requiredSizeIn(100.dp)
.background(Color.Green))
Text(text = "widthIn(max)")
BoxWithConstraints(
modifier = Modifier
.width(100.dp)
.border(3.dp, Color.Green)
) {
Box(
modifier = Modifier
.requiredWidthIn(min = 20.dp, max = 50.dp)
.height(50.dp)
.background(Color.Red)
)
}
Spacer(modifier = Modifier.height(10.dp))
BoxWithConstraints(
modifier = Modifier
.width(100.dp)
.border(3.dp, Color.Green)
) {
Box(
modifier = Modifier
.requiredWidthIn(min = 150.dp, max = 200.dp)
.height(50.dp)
.background(Color.Red)
)
}
}
}
约束条件
约束根据尺寸修改器、垂直/水平滚动或父级选择限制或想要使用最小或最大尺寸的方式而变化。
我的设备上的最大设备宽度为 1080px,在下面的示例中 200.dp 为 525px。并使用了verticalScroll,这就是为什么高度是用Constraints.Infinity
@Composable
fun ConstraintsSample3() {
Column(modifier = Modifier) {
Text(text = "No Dimension Modifier")
BoxWithConstraints(modifier = Modifier.background(Brown400)) {
val hasBoundedWidth = constraints.hasBoundedWidth
val hasFixedWidth = constraints.hasFixedWidth
val minWidth = constraints.minWidth
val maxWidth = constraints.maxWidth
val hasBoundedHeight = constraints.hasBoundedHeight
val hasFixedHeight = constraints.hasFixedHeight
val minHeight = constraints.minHeight
val maxHeight = constraints.maxHeight
Text(
"minWidth: $minWidth, maxWidth: $maxWidth\n" +
"hasBoundedWidth: $hasBoundedWidth, hasFixedWidth: $hasFixedWidth\n" +
"minHeight: $minHeight, maxHeight: $maxHeight\n" +
"hasBoundedHeight: $hasBoundedHeight, hasFixedHeight: $hasFixedHeight",
color = Color.White
)
}
Spacer(modifier = Modifier.height(10.dp))
Text(text = "FillMaxWidth and 200.dp Height")
BoxWithConstraints(
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
.background(Red400)
) {
val hasBoundedWidth = constraints.hasBoundedWidth
val hasFixedWidth = constraints.hasFixedWidth
val minWidth = constraints.minWidth
val maxWidth = constraints.maxWidth
val hasBoundedHeight = constraints.hasBoundedHeight
val hasFixedHeight = constraints.hasFixedHeight
val minHeight = constraints.minHeight
val maxHeight = constraints.maxHeight
Text(
"minWidth: $minWidth, maxWidth: $maxWidth\n" +
"hasBoundedWidth: $hasBoundedWidth, hasFixedWidth: $hasFixedWidth\n" +
"minHeight: $minHeight, maxHeight: $maxHeight\n" +
"hasBoundedHeight: $hasBoundedHeight, hasFixedHeight: $hasFixedHeight",
color = Color.White
)
}
Spacer(modifier = Modifier.height(10.dp))
Text(text = "wrapContentSize()")
BoxWithConstraints(
modifier = Modifier
.wrapContentSize()
.background(Orange400)
) {
val hasBoundedWidth = constraints.hasBoundedWidth
val hasFixedWidth = constraints.hasFixedWidth
val minWidth = constraints.minWidth
val maxWidth = constraints.maxWidth
val hasBoundedHeight = constraints.hasBoundedHeight
val hasFixedHeight = constraints.hasFixedHeight
val minHeight = constraints.minHeight
val maxHeight = constraints.maxHeight
Text(
"minWidth: $minWidth, maxWidth: $maxWidth\n" +
"hasBoundedWidth: $hasBoundedWidth\n" +
"hasFixedWidth: $hasFixedWidth\n" +
"minHeight: $minHeight\n" +
"maxHeight: $maxHeight\n" +
"hasBoundedHeight: $hasBoundedHeight\n" +
"hasFixedHeight: $hasFixedHeight",
color = Color.White
)
}
Spacer(modifier = Modifier.height(10.dp))
Text(text = "200.dp Width and Height")
BoxWithConstraints(
modifier = Modifier
.width(200.dp)
.height(200.dp)
.background(Green400)
) {
val hasBoundedWidth = constraints.hasBoundedWidth
val hasFixedWidth = constraints.hasFixedWidth
val minWidth = constraints.minWidth
val maxWidth = constraints.maxWidth
val hasBoundedHeight = constraints.hasBoundedHeight
val hasFixedHeight = constraints.hasFixedHeight
val minHeight = constraints.minHeight
val maxHeight = constraints.maxHeight
Text(
"minWidth: $minWidth, maxWidth: $maxWidth\n" +
"hasBoundedWidth: $hasBoundedWidth, hasFixedWidth: $hasFixedWidth\n" +
"minHeight: $minHeight, maxHeight: $maxHeight\n" +
"hasBoundedHeight: $hasBoundedHeight, hasFixedHeight: $hasFixedHeight",
color = Color.White
)
}
}
}
@Composable
private fun BoxWithConstraintsSample4() {
Text(text = "200.dp WidthIn(min) and HeightIn(min)")
BoxWithConstraints(
modifier = Modifier
.widthIn(min = 200.dp)
.heightIn(200.dp)
.background(Blue400)
) {
val hasBoundedWidth = constraints.hasBoundedWidth
val hasFixedWidth = constraints.hasFixedWidth
val minWidth = constraints.minWidth
val maxWidth = constraints.maxWidth
val hasBoundedHeight = constraints.hasBoundedHeight
val hasFixedHeight = constraints.hasFixedHeight
val minHeight = constraints.minHeight
val maxHeight = constraints.maxHeight
Text(
"minWidth: $minWidth, maxWidth: $maxWidth\n" +
"hasBoundedWidth: $hasBoundedWidth, hasFixedWidth: $hasFixedWidth\n" +
"minHeight: $minHeight, maxHeight: $maxHeight\n" +
"hasBoundedHeight: $hasBoundedHeight, hasFixedHeight: $hasFixedHeight",
color = Color.White
)
}
Text(text = "200.dp requiredWidth(min) and requiredHeight(min)")
BoxWithConstraints(
modifier = Modifier
.requiredWidthIn(min = 200.dp)
.requiredHeightIn(200.dp)
.background(Pink400)
) {
val hasBoundedWidth = constraints.hasBoundedWidth
val hasFixedWidth = constraints.hasFixedWidth
val minWidth = constraints.minWidth
val maxWidth = constraints.maxWidth
val hasBoundedHeight = constraints.hasBoundedHeight
val hasFixedHeight = constraints.hasFixedHeight
val minHeight = constraints.minHeight
val maxHeight = constraints.maxHeight
Text(
"minWidth: $minWidth, maxWidth: $maxWidth\n" +
"hasBoundedWidth: $hasBoundedWidth, hasFixedWidth: $hasFixedWidth\n" +
"minHeight: $minHeight, maxHeight: $maxHeight\n" +
"hasBoundedHeight: $hasBoundedHeight, hasFixedHeight: $hasFixedHeight",
color = Color.White
)
}
Text(text = "200.dp defaultMinSize()")
BoxWithConstraints(
modifier = Modifier
.defaultMinSize(200.dp)
.background(Pink400)
) {
val hasBoundedWidth = constraints.hasBoundedWidth
val hasFixedWidth = constraints.hasFixedWidth
val minWidth = constraints.minWidth
val maxWidth = constraints.maxWidth
val hasBoundedHeight = constraints.hasBoundedHeight
val hasFixedHeight = constraints.hasFixedHeight
val minHeight = constraints.minHeight
val maxHeight = constraints.maxHeight
Text(
"minWidth: $minWidth, maxWidth: $maxWidth\n" +
"hasBoundedWidth: $hasBoundedWidth, hasFixedWidth: $hasFixedWidth\n" +
"minHeight: $minHeight, maxHeight: $maxHeight\n" +
"hasBoundedHeight: $hasBoundedHeight, hasFixedHeight: $hasFixedHeight",
color = Color.White
)
}
Text(text = "200.dp WidthIn(max)")
BoxWithConstraints(
modifier = Modifier
.widthIn(max = 200.dp)
.background(Purple400)
) {
val hasBoundedWidth = constraints.hasBoundedWidth
val hasFixedWidth = constraints.hasFixedWidth
val minWidth = constraints.minWidth
val maxWidth = constraints.maxWidth
val hasBoundedHeight = constraints.hasBoundedHeight
val hasFixedHeight = constraints.hasFixedHeight
val minHeight = constraints.minHeight
val maxHeight = constraints.maxHeight
Text(
"minWidth: $minWidth, maxWidth: $maxWidth\n" +
"hasBoundedWidth: $hasBoundedWidth, hasFixedWidth: $hasFixedWidth\n" +
"minHeight: $minHeight, maxHeight: $maxHeight\n" +
"hasBoundedHeight: $hasBoundedHeight, hasFixedHeight: $hasFixedHeight",
color = Color.White
)
}
}