Search code examples
androidandroid-jetpackandroid-jetpack-compose

adjustViewBounds analogue in Jetpack Compose


I'm trying to make an image take up container width and have height based on image ratio. In XML, I would use adjustViewBounds on ImageView. Is there an analogue in Compose? If not, how can I achieve this?


Solution

  • Update for Compose 1.0+

    SimpleImage is deprecated and replaced by Image which is bit more customisable - at least it allows to set modifiers. The general idea of maintaining image ratio stays the same:

    val painter = painterResource(id = R.drawable.android_studio_logo)
    val imageRatio = painter.intrinsicSize.width / painter.intrinsicSize.height
    Image(
        painter = painter,
        contentDescription = null,
        modifier = Modifier
            .fillMaxWidth()
            .aspectRatio(imageRatio)
    )
    

    Old answer for 0.1.0-dev06

    I don't think that something like adjustViewBounds is currently supported out of the box in 0.1.0-dev06.

    By looking at the source code, SimpleImage doesn't seem to be customizable. All it does is drawing the image over the Box with exact same size as the image:

    @Composable
    fun SimpleImage(
        image: Image,
        tint: Color? = null
    ) {
        with(DensityAmbient.current) {
            val imageModifier = ImagePainter(image).toModifier(
                scaleFit = ScaleFit.FillMaxDimension,
                colorFilter = tint?.let { ColorFilter(it, BlendMode.srcIn) }
            )
            Box(LayoutSize(image.width.toDp(), image.height.toDp()) + ClipModifier + imageModifier)
        }
    }
    

    But based on that implementation, effect like adjustViewBounds can be achieved by using different size modifier. Instead of specific exact size we can apply LayoutWidth.Fill to occupy entire width and then adjust height using LayoutAspectRatio with the ratio of the image:

    val image = imageResource(R.drawable.android_studio_logo)
    val imageRatio = image.width.toFloat() / image.height.toFloat()
    val imageModifier = ImagePainter(image).toModifier(scaleFit = ScaleFit.FillMaxDimension)
    Box(LayoutWidth.Fill + LayoutAspectRatio(imageRatio) + imageModifier)
    

    Of course for better reusability and readability we can wrap it in a function.
    Here is how the result looks like:

    preview comparison