How to load Image from drawable in Jetpack compose?

Viewed 63727

I have tried below code but it reflects nothing in the UI, I'm missing anything here?

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            loadUi()
        }
    }

    @Composable
    fun loadUi() {
        CraneWrapper {
            MaterialTheme {
                Image(
                    (ResourcesCompat.getDrawable(
                        resources,
                        R.mipmap.ic_launcher,
                        null
                    ) as BitmapDrawable).bitmap
                )
            }
        }
    }
}
11 Answers

You can use the painterResource function:

 Image(painterResource(R.drawable.ic_xxxx),"content description")

The resources with the given id must point to either fully rasterized images (ex. PNG or JPG files) or VectorDrawable xml assets.
It means that this method can load either an instance of BitmapPainter or VectorPainter for ImageBitmap based assets or vector based assets respectively.

Example:

Card(
    modifier = Modifier.size(48.dp).tag("circle"),
    shape = CircleShape,
    elevation = 2.dp
) {
    Image(
        painterResource(R.drawable.ic_xxxx),
        contentDescription = "",
        contentScale = ContentScale.Crop,
        modifier = Modifier.fillMaxSize()
    )
}

enter image description here

Starting at version 1.0.0-beta01:

Image(
    painter = painterResource(R.drawable.your_drawable),
    contentDescription = "Content description for visually impaired"
)

Working in 0.1.0-dev14

Loading drawable in Image could be achieve from this:

Image(
      imageResource(id = R.drawable.scene_01),
      modifier = Modifier.preferredHeightIn(160.dp, 260.dp)
                    .fillMaxWidth(),
      contentScale = ContentScale.Crop
   )

Now, I'm trying to upload drawable in Circle Image that sounds tricky but too easy in JetPack Compose. You can do achieve in this way:

Image(
         asset = imageResource(id = R.drawable.scene_01),
         modifier = Modifier.drawBackground(
                    color = Color.Black,
                    style = Stroke(4f),
                    shape = CircleShape
          ).preferredSize(120.dp)
                    .gravity(Alignment.CenterHorizontally)
                    .clip(CircleShape),
          contentScale = ContentScale.FillHeight
      )

Output:

enter image description here

As imageResourceis not available anymore, the solutions with painterResource are indeed correct, e.g.

Image(painter = painterResource(R.drawable.ic_heart), contentDescription = "content description")

But you can actually still use Bitmap instead of drawable if you need so:

Image(bitmap = bitmap.asImageBitmap())

.asImageBitmap() is an extensions on Bitmap that compose provides and it creates an ImageBitmap from the given Bitmap.

version=1.0.0-beta01,use painterResource,imageResource has been deleted.

example

Image(
    painterResource(R.drawable.ic_vector_or_png),
    contentDescription = null,
    modifier = Modifier.requiredSize(50.dp)
)

android developer doc

@Composable
fun loadUi() {
val image = +imageResource(R.drawable.header)
    CraneWrapper {
        MaterialTheme {
            Container(expanded = true,height = 180.dp) {
                //Use the Clip() function to round the corners of the image
                Clip(shape = RoundedCornerShape(8.dp)) {
                //call DrawImage() to add the graphic to the app
                    DrawImage(image)
                }
            }
        }
    }
}

Try This one but if you copy the code and then paste it I don't know why but it won't work so just type it as it is and replace the image id

Image(
  painter = painterResource(id = R.drawable.tanjim),
  contentDescription = null,
)

I found that there is a function imageFromResource() in AndroidImage.kt:

fun imageFromResource(res: Resources, resId: Int): Image {
    return AndroidImage(BitmapFactory.decodeResource(res, resId))
}

so your code would be:

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        loadUi()
    }
}

@Composable
fun loadUi() {
    CraneWrapper {
        MaterialTheme {
            val image = imageFromResource(resources, R.mipmap.ic_launcher)
            SimpleImage(image)
        }
    }
}

}

With version 1.0.0-beta01

It's like below

Image(
  painter = painterResource(R.drawable.header),
  contentDescription = null,
)

I found SimpleImage class from jetpack compose library to load the image but this is a temporary solution, and I didn't find any styling option with this yet.

// TODO(Andrey) Temporary. Should be replaced with our proper Image component when it available
@Composable
fun SimpleImage(
    image: Image
) {
    // TODO b132071873: WithDensity should be able to use the DSL syntax
    WithDensity(block = {
        Container(width = image.width.toDp(), height = image.height.toDp()) {
            Draw { canvas, _ ->
                canvas.drawImage(image, Offset.zero, Paint())
            }
        }
    })
}

I have used it in this way

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            loadUi()
        }
    }

    @Composable
    fun loadUi() {
        CraneWrapper {
            MaterialTheme {
                val bitmap = (ResourcesCompat.getDrawable(
                        resources,
                        R.mipmap.ic_launcher,
                        null
                    ) as BitmapDrawable).bitmap
                SimpleImage(Image(bitmap))
            }
        }
    }
}

Still, I'm not sure this is the correct way of loading image from drawables.

Google updated their API. For 0.1.0-dev03 loading images is synchronous and is done this way

val icon = +imageResource(R.drawable.ic_xxx)

To draw the image

Container(modifier = Height(100.dp) wraps Expanded) {
   DrawImage(icon)
}

Currently the above code relies on you specifying either the exact height or width. It seems that scaling the image is not supported if you want for example 100 dp height and wrap_content instead of Expanded which expands the full width. Does any one know how to solve this issue? Also is possible to fit the image inside it's container like old way scaleType=fitCenter?

Related