Have anyone a suggestion on how to mimick the XML ...
# compose
r
Have anyone a suggestion on how to mimick the XML ImageView's android:scaleType="fitCenter" in JetPack Compose ? Have tried to wrap a DrawImage in a Container with a dedicated size (i.e 40.dpx40.dp), for all my square images, this seems ok, but on images which is either higher or wider, the image doesn't resize so it fits into the square, it gets cut off either in height or in width. It should also keep its aspect ratio if it resizes.
Copy code
Container(
                                width = 40.dp,
                                height = 40.dp
                            ) {
                                DrawImage(image)
                            }
RG
Actually I found an approach by thinking...again. My trick is to make a double wrap of
Container
and resize the inner one by calculating the aspect ratio of the image.
Copy code
Column()
            {
                var imageWidth: Int = image.width;
                var imageHeight: Int = image.height;
                var imageAspect: Double = image.width.toDouble()/image.height.toDouble()

                var justWidth: Double = 0.0
                var justHeight: Double = 0.0

                FlexRow {
                    inflexible{
                        Padding(padding = 4.dp){                          
                            Container(
                                width = 40.dp,
                                height = 40.dp) {

                                if(imageAspect>1.0) {
                                    justWidth = 40.0
                                    justHeight = 40/imageAspect
                                } else {
                                    justWidth = 40*imageAspect
                                    justHeight = 40.0
                                }

                                Container(
                                    width = justWidth.dp,
                                    height = justHeight.dp
                                ) {
                                    DrawImage(image)
                                }
                            }
                        }

                    }

                    inflexible {
                        Column {
                            Text(text = "w=${imageWidth} h=${imageHeight}" +
                                    " aspect=${imageAspect}")
                            Text(text = "jw=${justWidth} jh=${justHeight}")

                        }
                    }
                }
            }
RG
a
We are going to add scaleType-like param for DrawImage soon
r
Wow, thats good !! You have my suggestion here...
Here's a more general
@Composable
function version, where the containing size of the image can be of any aspect ratio, and the image fits in center of that aspect ratio.
Copy code
@Composable
fun DrawImageFitCenter(
    image: Image,
    tint: Color? = null,
    containerWidthDp: Int,
    containerHeightDp: Int
){
    val imageWidth: Int = image.width
    val imageHeight: Int = image.height
    val imageAspect: Double = imageWidth.toDouble()/imageHeight.toDouble()
    val containerAspect: Double = containerWidthDp.toDouble()/containerHeightDp.toDouble()

    var justWidth: Double = 0.0
    var justHeight: Double = 0.0

    Container(
        width = containerWidthDp.dp,
        height = containerHeightDp.dp
    ) {
        if(containerAspect>imageAspect)
        {
            justWidth = containerWidthDp.toDouble()*(imageAspect/containerAspect)
            justHeight = containerHeightDp.toDouble()
        } else {
            justWidth = containerWidthDp.toDouble()
            justHeight = containerHeightDp.toDouble()*(containerAspect/imageAspect)
        }

        Container(
            width = justWidth.dp,
            height = justHeight.dp
        ) {
            DrawImage(
                image = image, 
                tint = tint )
        }

    }
}
RG
Isn't there any "conversion" from
Dp
to
Int
?
z
I believe you can convert
Dp
to pixels by using
withDensity
r
@Zach Klippenstein (he/him) [MOD] Will the result be an Int with withDensity?, I need that to calculate the aspect ratio. I could ofcourse convert it to a string, strip the "dp" at the end and convert it though... to a Double or to an Int. Anyhow i wonder if anyone had defined that wheel in @Compose...
Although looking at the
Dp
kdoc, it already supports all the arithmetic operators directly so I don't think you need to do any conversions. https://developer.android.com/reference/kotlin/androidx/ui/core/Dp.html
r
@Zach Klippenstein (he/him) [MOD] Trouble was that using dp aritmethics I ended in a situation where I want to multiply or divide a dp with a dp... there isn't any dp.mul(dp) or dp.div(dp) like operators. ...so far as I know...
z
What do you mean? There are those exact operators on that page I just linked.
r
Ok, see that now... will try to rework the DrawImageFitCenter...
@Zach Klippenstein (he/him) [MOD] Well... when dividing dp by dp i get a float... (I expected another dp) ...but i see the reason (mathematically). Multiplying a dp with a float I got a dp... ... as an old druid, I really want to use Double instead of Float, bit I see the world is moving forward...
Is there a good reason for mnemonics here ? (i see div, but minus, plus, and times... i'd expected sub, add and mul...)
z
Those are the names required for the operator functions. Don't call
imageWidth.div(imageHeight)
directly, do
imageWidth / imageHeight
. More info here: https://kotlinlang.org/docs/reference/operator-overloading.html
r
On suggestion from @Zach Klippenstein (he/him) [MOD] I have changed the code:
Copy code
@Composable
fun DrawImageFitCenter(
        modifier: Modifier = Modifier.None,
        image: Image,
        tint: Color? = null,
        containerWidth: Dp,
        containerHeight: Dp
){
    val imageAspect = image.width.dp / image.height.dp
    val containerAspect = containerWidth / containerHeight

    var justWidth: Dp
    var justHeight: Dp

    Container(
            modifier = modifier,
            width = containerWidth,
            height = containerHeight
    ) {
        if(containerAspect>imageAspect)
        {
            justWidth = containerWidth*(imageAspect/containerAspect)
            justHeight = containerHeight
        } else {
            justWidth = containerWidth
            justHeight = containerHeight*(containerAspect/imageAspect)
        }

        Container(width = justWidth, height = justHeight) {
            DrawImage(image = image,
                    tint = tint)

        }
    }
}