How to set drawable as a background to image in jetpack compose?

Viewed 11273

How to set a drawable resource as a background to an Image in Jetpack compose?

Corresponding view XML code

<androidx.appcompat.widget.AppCompatImageView
    android:background="@drawable/drawable_black_circle"
    android:src="@drawable/app_logo"
    ... 
/>

My current code,

Image(
    painter = painterResource(id = R.drawable.app_logo),
    contentDescription = null,
    modifier = Modifier
        .height(160.dp)
        .width(160.dp)
        .padding(32.dp),
)

Modifier.background() gives me the option to use color as a background.
Similarly looking for a way to use a drawable resource as a background.

Note:
Looking for a way to have the background in the image.
Not looking for enclosing the image inside another composable with the background.

2 Answers

You can place two images in a Box, so main one will be on top of the background.

If you are going to use such view extensively, you can create your own composable which can be used simply like this:

ImageWithBackground(
    painter = painterResource(id = R.drawable.app_logo),
    backgroundDrawableResId = R.drawable.background,
    contentDescription = "",
    modifier = Modifier
        .height(160.dp)
        .width(160.dp)
        .padding(32.dp),
)

Composable:

@Composable
fun ImageWithBackground(
    painter: Painter,
    @DrawableRes backgroundDrawableResId: Int,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    alignment: Alignment = Alignment.Center,
    contentScale: ContentScale = ContentScale.Fit,
    alpha: Float = DefaultAlpha,
    colorFilter: ColorFilter? = null
) {
    Box(
        modifier = modifier
    ) {
        Image(
            painter = painterResource(backgroundDrawableResId),
            contentDescription = null,
            modifier = Modifier
                .matchParentSize()
        )
        Image(
            painter = painter,
            contentDescription = contentDescription,
            alignment = alignment,
            contentScale = contentScale,
            alpha = alpha,
            colorFilter = colorFilter,
            modifier = Modifier
                .matchParentSize()
        )
    }
}

Sir if you absolutely do not wish to nest the image inside another, you could build it using Canvas. However, I don't see a problem here since under the hood, that's what it is — an image on top of another. A Box is just a positioning mechanism. If your decide to go for Canvas, this is how to go about using it:

val backgroundVector = ImageVector.vectorResource(id = R.drawable.ic_launcher_foreground)
val backgroundPainter = rememberVectorPainter(image = backgroundVector)

val foregroundVector = ... // Same as above
val foregroundPainter = rememberVectorPainter(...) // Same as above

Canvas(modifier = Modifier.fillMaxSize()) {
    with(backgroundPainter) {
        draw(painter.intrinsicSize) // You can scale and modify, all the good stuff
    }
    with(foregroundPainter) {
        // Ditto as above,
    }
}

There's also the transform scope available, or the individual translate, rotate, and scale, maybe more.

Related