saket / telephoto

Building blocks for designing media experiences in Compose UI
https://saket.github.io/telephoto/
Apache License 2.0
998 stars 33 forks source link

Incorrect image bounds with `Modifier.wrapContentSize()` #111

Open saket opened 3 weeks ago

saket commented 3 weeks ago

ZoomableImage() does not correctly measure images when Modifier.wrapContentSize() is used.

Expected: Image() Actual: ZoomableImage()
image zoomableimage
Image(
  modifier = Modifier.wrapContentSize(),
  painter = assetPainter("cat_1920.jpg"),
  contentDescription = null,
  contentScale = ContentScale.Crop,
  alignment = Alignment.BottomCenter,
)
ZoomableImage(
  modifier = Modifier.wrapContentSize(),
  image = ZoomableImageSource.asset("cat_1920.jpg"),
  contentDescription = null,
  contentScale = ContentScale.Crop,
  alignment = Alignment.BottomCenter,
)
@Composable
internal fun ZoomableImageSource.Companion.asset(assetName: String): ZoomableImageSource {
  val painter = assetPainter(assetName)
  return remember(painter) {
    object : ZoomableImageSource {
      @Composable
      override fun resolve(canvasSize: Flow<Size>): ResolveResult {
        return ResolveResult(
          delegate = ZoomableImageSource.PainterDelegate(painter)
        )
      }
    }
  }
}

@Composable
private fun assetPainter(assetName: String): Painter {
  val context = LocalContext.current
  return remember(assetName) {
    context.assets.open(assetName).use { stream ->
      BitmapPainter(BitmapFactory.decodeStream(stream).asImageBitmap())
    }
  }
}