How do I load url into Image into DrawImage in Compose UI Android Jetpack?

Viewed 14060

I can use val image = +imageResource(R.drawable.header) and use DrawImage(image) to load image from Drawable Resource,

But how do I load a string url into the DrawImage(image)?. I've tried using Glide, but it needs to load into imageView. meanwhile DrawImage(image) doesn't take input from imageView.

Thanks.

12 Answers

Staring with 1.0.x the best way to achieve it is to use the Coil-Compose library.

Add in your build.gradle the dependency

dependencies {
    implementation("io.coil-kt:coil-compose:1.3.1")
}

Then just use:

Image(
    painter = rememberImagePainter("your url"),
    contentDescription = "My content description",
)

This loads the url passed in with rememberImagePainter, and then displays the resulting image using the standard Image composable.

Coil for Jetpack Compose

Another option to load an image from the internet.

Add the Coil dependency to build.gradle :

dependencies {
    implementation "io.coil-kt:coil-compose:1.4.0")
}

Simple use:

Image(
    painter = rememberImagePainter("https://picsum.photos/300/300"),
    contentDescription = stringResource(R.string.image_content_desc)
)

Don't forget to add the internet permission (AndroidManifest.xml)

<uses-permission android:name="android.permission.INTERNET"/>

More custom here: Jetpack Compose - Coil Document

A solution loading a Bitmap from the url and using the asImageAsset() Bitmap extension method :

@Composable
fun loadPicture(url: String): UiState<Bitmap> {
    var bitmapState: UiState<Bitmap> by state<UiState<Bitmap>> { UiState.Loading }

    Glide.with(ContextAmbient.current)
        .asBitmap()
        .load(url)
        .into(object : CustomTarget<Bitmap>() {
            override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                bitmapState = UiState.Success(resource)
            }

            override fun onLoadCleared(placeholder: Drawable?) { }
        })

    return bitmapState
}

Use the function with your Image() like this :

val loadPictureState = loadPicture(url)
if (loadPictureState is UiState.Success<Bitmap>)
    Image(loadPictureState.data.asImageAsset())
else
    Text("Loading...")

This snippet is using the Glide library and the UiState helper function from the JetNews official Google sample for Jetpack Compose

You can use remember to watch a bitmap, then fetch it using Glide and update it as soon as you got it.

var bitmap by remember { mutableStateOf<Bitmap?>(null)}

Glide.with(ContextAmbient.current).asBitmap()
    .load("https://picsum.photos/200/300")
    .into(object : CustomTarget<Bitmap>() {
        override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
             bitmap = resource
          }

          override fun onLoadCleared(placeholder: Drawable?) {}
      })

You can then use it like this:


if (bitmap != null )
    Image(bitmap!!.asImageAsset(), Modifier.fillMaxWidth())
else
    Text("Loading Image...")

(This is a modern version of bviale's answer)

After Jetpack's beta release, using accompanist - Utils library for Jetpack Compose is the cleanest way for the above-mentioned use case.

add

dependencies {
    implementation "com.google.accompanist:accompanist-glide:0.10.0"
}

and then

    import androidx.compose.foundation.Image
    import com.google.accompanist.glide.rememberGlidePainter
    
    Image(
        painter = rememberGlidePainter("https://picsum.photos/300/300"),
        contentDescription = stringResource(R.string.image_content_desc),
        previewPlaceholder = R.drawable.placeholder,
    )

for now you can use "io.coil-kt:coil-compose:1.3.1"

For Compose 1.1.0 this snippet works like a charm, it shows the placeholder in Composable Preview:

@Composable
fun loadPicture(url: String, placeholder: Painter? = null): Painter? {

  var state by remember {
    mutableStateOf(placeholder)
  }

  val options: RequestOptions = RequestOptions().autoClone().diskCacheStrategy(DiskCacheStrategy.ALL)
  val context = LocalContext.current
  val result = object : CustomTarget<Bitmap>() {
    override fun onLoadCleared(p: Drawable?) {
      state = placeholder
    }

    override fun onResourceReady(
      resource: Bitmap,
      transition: Transition<in Bitmap>?,
    ) {
      state = BitmapPainter(resource.asImageBitmap())
    }
  }
  try {
    Glide.with(context)
      .asBitmap()
      .load(url)
      .apply(options)
      .into(result)
  } catch (e: Exception) {
    // Can't use LocalContext in Compose Preview
  }
  return state
}
@Composable
fun ImageItem() {
  val painter = loadPicture(
    url = item.image.fragments.image.href,
    placeholder = painterResource(id = R.drawable.tc_ic_no_image)
  )
  if (painter != null) {
    Image(painter = painter)
  }
}

Add the Coil dependency to build.gradle :

dependencies {
      implementation "io.coil-kt:coil-compose:1.4.0")
}

Implementation in Code :

 Image(painter = rememberImagePainter(data = "https://image.tmdb.org/t/p/original/rr7E0NoGKxvbkb89eR1GwfoYjpA.jpg",
                                                builder = {
                                                    crossfade(true)
                                                    transformations(CircleCropTransformation())
                                                }),
                contentDescription = "Movie Poster")

With the latest version of Coil - 2.1.0, rememberImagePainter() has been deprecated. AsyncImage has been introduced.

AsyncImage is a composable that that executes an image request asynchronously and renders the result. It supports the same arguments as the standard Image composable and additionally it supports setting placeholder/error/fallback painters and onLoading/onSuccess/onError callbacks.

Below is a simple example of how to use AsyncImage to load an image from a URL:

AsyncImage(
    model = "https://example.com/image.jpg",
    contentDescription = null
)

You can check the docs for more comprehensive explanation of AsyncImage

I have found a very easy way to show an image from an URL.

  1. Add dependencies{ implementation("io.coil-kt:coil:1.4.0") }

  2. Just do this

    imageView.load("https://www.example.com/image.jpg")

Also for a resource o file you can do this:

imageView.load(R.drawable.image)

imageView.load(File("/path/to/image.jpg"))

Requests can be configured with an optional trailing lambda:

imageView.load("https://www.example.com/image.jpg") {
    crossfade(true)
    placeholder(R.drawable.image)
    transformations(CircleCropTransformation())
}

I found this info from official coil page here: enter link description here

Try to use https://github.com/skydoves/landscapist

It seems to be realy good library to load images along with glide, coil, etc It enables to override handlers to do any custom things, e.q. when you got an error or during loading phase

Related