简体   繁体   English

Jetpack Compose - 使图像缩放到列/行中的可用大小

[英]Jetpack Compose - Make Image scale to the available size in Column/Row

Consider the following image:考虑下图:

在此处输入图像描述

I have a Column that has an Image together with another Column that has some Text elements.我有一个包含ImageColumn和另一个包含一些Text元素的Column What I'm trying to do is to have the Image scale uniformly to the available space.我想要做的是让Image均匀地缩放到可用空间。 I just can't make it work.我只是无法让它发挥作用。

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

One of the things that I tried was setting the size of the Image to fillMaxSize and the weight of the second Column to 1f , but it didn't do anything.我尝试过的其中一件事是将Image的大小设置为fillMaxSize并将第二Columnweight设置为1f ,但它没有做任何事情。 Maybe I need to have the size of the second Column fixed?也许我需要固定第二Column的大小? Any help is very appreciated.非常感谢任何帮助。

It seems to your image size is less than the screen max width, for that reason the container of the image fill the width, but the image remains small, if you fill the height on the image it scales correctly but the image container fills all space leaving below the list.您的图像尺寸似乎小于屏幕最大宽度,因此图像的容器填充了宽度,但图像仍然很小,如果您填充图像的高度,它会正确缩放,但图像容器会填充所有空间离开列表下方。 You could try setting and aspect ratio to the modifier to prevent container from filling all available 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
)
...

结果

You haven't used Modifier.weight on the correct child.您没有在正确的孩子上使用Modifier.weight It should be applied to the view, which you need to fill the rest of the parent.它应该应用于视图,您需要填写父级的rest。

The parent will divide the vertical space remaining after measuring unweighted child elements and distribute it according to this weight.父级将测量未加权的子元素后剩余的垂直空间划分并根据此权重分配。

Image(
    modifier = Modifier.weight(1f),
    painter = painterResource(R.drawable.my_image_1),
    contentDescription = null,
    contentScale = ContentScale.Fit
)
Column(
    horizontalAlignment = Alignment.CenterHorizontally
) {
    repeat(20) {
        Text(text = "${it}")
    }
}

Couldn't get it work right using a Column , but I succeeded using a ConstraintLayout and Nestor's help with the aspectRatio .无法使用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")
        }
    }
}

在此处输入图像描述 在此处输入图像描述

But if someone thinks that it can still be done with a Column instead of a ConstraintLayout , he can post an answer and I may accept it.但是,如果有人认为仍然可以使用Column而不是ConstraintLayout来完成,他可以发布答案,我可以接受。

If we consider the height of the parent Column - as the sum of the heights of the Image and the nested Column - it can be argued that the height of your Image should be equal to the remainder of the height, after subtracting from the height of the parent Column - the height of the nested Column .如果我们考虑父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")
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM