简体   繁体   中英

How to use a 9 patch drawable (.9.png) in my screen using Jetpack Compose?

I'm trying to use a.9.png file in Image composable as:

            Image(
            painter = painterResource(id = R.drawable.shadow_faq),
            contentDescription = "Faq card 1",
            modifier = Modifier
                .constrainAs(imgGeneral) {
                    top.linkTo(glImgGeneralTop)
                    bottom.linkTo(glImgBottom)
                    start.linkTo(glImgLeft)
                    end.linkTo(glImgRight)
                    height = Dimension.fillToConstraints
                    width = Dimension.fillToConstraints
                }
        )

But on doing this I get a render problem that says java.lang.IllegalArgumentException: Only VectorDrawables and rasterized asset types are supported ex. PNG, JPG java.lang.IllegalArgumentException: Only VectorDrawables and rasterized asset types are supported ex. PNG, JPG

How do I use a.9.png file with Jetpack Compose?

You can use the DrawablePainter from Accompanist that returns a Painter which draws an Android Drawable .

Image(
    rememberDrawablePainter(drawable = ContextCompat.getDrawable(context,R.drawable.xxxx) ),
    contentDescription = "Faq card 1"
)

Update : Starting with 1.0.0-rc02 and accompanist 0.14.0 you can use the coil-compose version:

Image(
    rememberImagePainter(ContextCompat.getDrawable(context,R.drawable.xxx)),
    contentDescription = "Faq card 1",
)

You can use AndroidView and pass old good ImageView

AndroidView(
    modifier = Modifier.xxx,
    factory = {
        ImageView(it)
    }
)
{
    it.setImageResource(R.drawable.shadow_faq)
}

Edited: Please, use Gabriele answer.

I tried the Gabriele solution, but didn't work for me when I set a specific size like 100x200.

Here's my solution...

val context = LocalContext.current
val (w, h) = with(LocalDensity.current) {
    200.dp.roundToPx() to 100.dp.roundToPx()
}
val image = remember {
    ContextCompat.getDrawable(context, R.drawable.balao)?.toBitmap(w, h)?.asImageBitmap()!!
}
Image(image, contentDescription = null)

since coil-compose moved out of Accompanist to coil, rememberDrawablePainter become private .

But there's no reason for using an internal api: rememberImagePainter (prev rememberCoilPainter ) takes any object as a data, including drawable:

@Composable
fun rememberDrawablePainter(@DrawableRes id: Int): ImagePainter {
    val context = LocalContext.current
    val drawable = remember {
        ContextCompat.getDrawable(context, id)
    }
    return rememberImagePainter(data = drawable)
}

You need to initialise drawable inside remember to prevent it from being recreated on each redraw.

ps Don't forget to add implementation("io.coil-kt:coil-compose:$coilVersion")

But still this is not optimal solution as ContextCompat.getDrawable gets called for each view, and in case of many views on the screen with same drawable(eg chat screen) it takes significant amount of time(over 0.1 sec just to load all drawables in my case)

I've created an issue about this problem: https://issuetracker.google.com/issues/193907127

sometimes ,we load 9.png to be a background of Views, just like the message item on your chat apps. And we could do like this:

first we load 9.png as a drawable:

 val bgImg = ContextCompat.getDrawable(
    LocalContext.current,
    if (isFromMe) R.drawable.chat_message_right else R.drawable.chat_message_left
)

second we could use Modifier#drawBehind() method to set a background :

Text(text = "This my message",
    modifier = Modifier
        .drawBehind {
            bgImg?.updateBounds(0, 0, size.width.toInt(), size.height.toInt())
            bgImg?.draw(drawContext.canvas.nativeCanvas)
        }
        .padding(8.dp)
)

At last ,you will get the effect you want .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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