Jetpack Compose - 将图像缩放到 Column/Row 中的可用大小
Jetpack Compose - Make Image scale to the available size in Column/Row
考虑下图:
我有一个 Column
有一个 Image
和另一个 Column
有一些 Text
元素。我想要做的是让 Image
统一缩放到可用的 space。我就是做不到。
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Cyan)
.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.SpaceEvenly
) {
Image(
modifier = Modifier.fillMaxWidth(),
painter = painterResource(R.drawable.rocket_boy),
contentDescription = null,
contentScale = ContentScale.Fit
)
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
repeat(20) {
Text(text = "${it}")
}
}
}
我尝试的其中一件事是将 Image
的大小设置为 fillMaxSize
并将第二个 Column
的 weight
的大小设置为 1f
,但它什么也没做。也许我需要固定第二个 Column
的大小?非常感谢任何帮助。
您的图像尺寸似乎小于屏幕最大宽度,因此图像的容器填充宽度,但图像仍然很小,如果您填充图像的高度,它会正确缩放,但图像容器填充列表下方的所有 space。您可以尝试为修饰符设置纵横比,以防止容器填充所有可用 space:
...
val painter = painterResource(id = R.drawable.ic_dismiss_24)
Image(
modifier = Modifier
.aspectRatio(ratio = painter.intrinsicSize.height /
painter.intrinsicSize.width)
.fillMaxWidth()
.fillMaxHeight(),
painter = painter,
contentDescription = null,
contentScale = ContentScale.Fit
)
...
您没有在正确的 child 上使用 Modifier.weight
。它应该应用于视图,您需要填充 parent.
的其余部分
The parent will divide the vertical space remaining after measuring unweighted child elements and distribute it according to this weight.
Modifier.weight
有参数 fill
,默认参数为 true
。此默认参数与 Modifier.fillMaxHeight()
相同(在 Column
的情况下),如果您不需要填充所有可用高度,您可以指定 false
:
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Cyan)
.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
) {
val painter = painterResource(R.drawable.ic_redo)
Image(
modifier = Modifier.weight(1f, fill = false)
.aspectRatio(painter.intrinsicSize.width / painter.intrinsicSize.height)
.fillMaxWidth(),
painter = painter,
contentDescription = null,
contentScale = ContentScale.Fit
)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
repeat(20) {
Text(text = "${it}")
}
}
}
使用 Column
无法正常工作,但我使用 ConstraintLayout
成功了,在 Nestor 的帮助下 aspectRatio
。
ConstraintLayout(
modifier = Modifier.fillMaxSize()
) {
val (button, text) = createRefs()
val painter = painterResource(R.drawable.rocket_boy)
Image(
modifier = Modifier
.aspectRatio(ratio = painter.intrinsicSize.width /
painter.intrinsicSize.height)
.padding(16.dp)
.constrainAs(text) {
top.linkTo(parent.top)
bottom.linkTo(button.top)
height = Dimension.preferredWrapContent
width = Dimension.preferredWrapContent
start.linkTo(parent.start)
end.linkTo(parent.end)
},
painter = painter,
contentDescription = null,
contentScale = ContentScale.Fit
)
Column(Modifier.constrainAs(button) {
bottom.linkTo(parent.bottom, margin = 16.dp)
top.linkTo(text.bottom)
start.linkTo(parent.start)
end.linkTo(parent.end)
height = Dimension.wrapContent
}) {
repeat(5) {
Text(text = "$it")
}
}
}
但如果有人认为用 Column
代替 ConstraintLayout
仍然可以完成,他可以 post 回答,我可以接受。
如果我们考虑父级 Column
的高度 - 作为 Image
和嵌套 Column
高度的总和 - 可以说你的高度Image
应该等于高度的余数,减去父级 Column
的高度 - 嵌套的 Column
.
的高度
var textInColumnSize by remember { mutableStateOf(Size.Zero) }
var globalColumnSize by remember { mutableStateOf(Size.Zero) }
val imageHeight: Dp =
LocalDensity.current.run { (globalColumnSize.height -
textInColumnSize.height).toDp() }
Column(
modifier = Modifier
.fillMaxSize()
.onGloballyPositioned { coordinates ->
globalColumnSize = coordinates.size.toSize()
}
.background(Color.Cyan)
.padding(horizontal = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceEvenly
) {
Image(
modifier = Modifier
.fillMaxWidth()
.height(imageHeight),
painter = painterResource(R.drawable.rocket_boy),
contentDescription = null,
)
Column(
modifier = Modifier
.fillMaxWidth()
.onGloballyPositioned { coordinates ->
textInColumnSize = coordinates.size.toSize()
},
horizontalAlignment = Alignment.CenterHorizontally
) {
repeat(10) {
Text(text = "$it")
}
}
}
考虑下图:
我有一个 Column
有一个 Image
和另一个 Column
有一些 Text
元素。我想要做的是让 Image
统一缩放到可用的 space。我就是做不到。
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Cyan)
.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.SpaceEvenly
) {
Image(
modifier = Modifier.fillMaxWidth(),
painter = painterResource(R.drawable.rocket_boy),
contentDescription = null,
contentScale = ContentScale.Fit
)
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
repeat(20) {
Text(text = "${it}")
}
}
}
我尝试的其中一件事是将 Image
的大小设置为 fillMaxSize
并将第二个 Column
的 weight
的大小设置为 1f
,但它什么也没做。也许我需要固定第二个 Column
的大小?非常感谢任何帮助。
您的图像尺寸似乎小于屏幕最大宽度,因此图像的容器填充宽度,但图像仍然很小,如果您填充图像的高度,它会正确缩放,但图像容器填充列表下方的所有 space。您可以尝试为修饰符设置纵横比,以防止容器填充所有可用 space:
...
val painter = painterResource(id = R.drawable.ic_dismiss_24)
Image(
modifier = Modifier
.aspectRatio(ratio = painter.intrinsicSize.height /
painter.intrinsicSize.width)
.fillMaxWidth()
.fillMaxHeight(),
painter = painter,
contentDescription = null,
contentScale = ContentScale.Fit
)
...
您没有在正确的 child 上使用 Modifier.weight
。它应该应用于视图,您需要填充 parent.
The parent will divide the vertical space remaining after measuring unweighted child elements and distribute it according to this weight.
Modifier.weight
有参数 fill
,默认参数为 true
。此默认参数与 Modifier.fillMaxHeight()
相同(在 Column
的情况下),如果您不需要填充所有可用高度,您可以指定 false
:
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Cyan)
.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
) {
val painter = painterResource(R.drawable.ic_redo)
Image(
modifier = Modifier.weight(1f, fill = false)
.aspectRatio(painter.intrinsicSize.width / painter.intrinsicSize.height)
.fillMaxWidth(),
painter = painter,
contentDescription = null,
contentScale = ContentScale.Fit
)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
repeat(20) {
Text(text = "${it}")
}
}
}
使用 Column
无法正常工作,但我使用 ConstraintLayout
成功了,在 Nestor 的帮助下 aspectRatio
。
ConstraintLayout(
modifier = Modifier.fillMaxSize()
) {
val (button, text) = createRefs()
val painter = painterResource(R.drawable.rocket_boy)
Image(
modifier = Modifier
.aspectRatio(ratio = painter.intrinsicSize.width /
painter.intrinsicSize.height)
.padding(16.dp)
.constrainAs(text) {
top.linkTo(parent.top)
bottom.linkTo(button.top)
height = Dimension.preferredWrapContent
width = Dimension.preferredWrapContent
start.linkTo(parent.start)
end.linkTo(parent.end)
},
painter = painter,
contentDescription = null,
contentScale = ContentScale.Fit
)
Column(Modifier.constrainAs(button) {
bottom.linkTo(parent.bottom, margin = 16.dp)
top.linkTo(text.bottom)
start.linkTo(parent.start)
end.linkTo(parent.end)
height = Dimension.wrapContent
}) {
repeat(5) {
Text(text = "$it")
}
}
}
但如果有人认为用 Column
代替 ConstraintLayout
仍然可以完成,他可以 post 回答,我可以接受。
如果我们考虑父级 Column
的高度 - 作为 Image
和嵌套 Column
高度的总和 - 可以说你的高度Image
应该等于高度的余数,减去父级 Column
的高度 - 嵌套的 Column
.
var textInColumnSize by remember { mutableStateOf(Size.Zero) }
var globalColumnSize by remember { mutableStateOf(Size.Zero) }
val imageHeight: Dp =
LocalDensity.current.run { (globalColumnSize.height -
textInColumnSize.height).toDp() }
Column(
modifier = Modifier
.fillMaxSize()
.onGloballyPositioned { coordinates ->
globalColumnSize = coordinates.size.toSize()
}
.background(Color.Cyan)
.padding(horizontal = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceEvenly
) {
Image(
modifier = Modifier
.fillMaxWidth()
.height(imageHeight),
painter = painterResource(R.drawable.rocket_boy),
contentDescription = null,
)
Column(
modifier = Modifier
.fillMaxWidth()
.onGloballyPositioned { coordinates ->
textInColumnSize = coordinates.size.toSize()
},
horizontalAlignment = Alignment.CenterHorizontally
) {
repeat(10) {
Text(text = "$it")
}
}
}