Coil: ImageView with one of its dimensions set to wrap_content does not work

Created on 13 Aug 2019  路  8Comments  路  Source: coil-kt/coil

Describe the bug
Assume the following ImageView:

<ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter" />

If you try to load an image to it, Coil will not calculate the correct width (based on the ImageView's fixed height and the aspect ratio of the image being loaded), and the ImageView will end up with a 0 width.

Using size() solves this issue, but it is not ideal because it is not always possible to know beforehand the dimensions of the image being loaded.

To Reproduce
Load an image to an ImageView which has one fixed dimension, and one wrap_content dimension.
Sample project: CoilWrapContent.zip

Expected behavior
Coil should automatically calculate the dimension set to wrap_content based on the fixed dimension & the dimensions of the image being loaded.

For example: If I load a 400x200 (2:1 aspect ratio) image to an ImageView with android:layout_width="wrap_content" and android:layout_height="100dp", then Coil should automatically set the width to 200dp (perhaps this shouldn't apply to all scaleTypes).

Logs/Screenshots
Layout Inspector screenshot showing the ImageView having its width set to 0:
image

Library version
0.6.0

bug

Most helpful comment

@fernandospr You can work around this by setting the scaleType to centerCrop or scale(Scale.FILL) on your request.

This occurs because wrap_content is evaluated to 1px whereas Glide and Picasso treat it as the height of the parent. I'm working on fixing this behaviour for 0.7.0.

All 8 comments

Good catch! I think this is because we force PixelSize's dimensions to be > 0. Relaxing that limitation to >= 0 should solve the issue, but might cause side-effects. Going to work on this later tonight.

Unfortunately #29 does not seem to fully solve the issue. On the sample app the ImageView now has a 1:1 aspect ratio instead of the 2:1 the image being loaded has:

image

@Stonos This is because the ImageView is set to scaleType="fitCenter", which will "fit" the image to the smallest dimension, which in this case is 1px. This will cause us to end up loading the image at 1x1. Changing to scaleType="centerCrop" or setting scale(Scale.FILL) on the request, will load the image in as intended.

I believe this is working as intended, but let me know if this seems unintuitive.

You're right, centerCrop works fine!

The reason I thought fitCenter would also work is because it works when setting an ImageView's src via XML:
image

Ah good point. Looks like ImageView uses the parent's dimensions in that case. I think we could do this in Coil, but need to verify. I'd like to keep the same behaviour between android:src and load. Going to re-open this issue to track.

I'm playing with a few different View measurement algorithms in the branch colin/view_size_experiment. I'm going to timebox this and ship the current behaviour in 0.6.1, though it's possible it might change in future versions.

Hi @colinrtwhite, I'm using 0.6.1 and using wrap_content for both width and height doesn't work either. This was my first test of the library and I was surprised it didn't work out of the box, wondering what I did wrong, until I tried using fixed values for width/height.

I'm not sure if this is the expected behavior. If it is, then I suggest you to add a comment about this on the migration guide from libraries such as Glide or Picasso which do work using wrap_content out of the box and it's possible that ImageViews are using wrap_content.

Sample using Picasso, Glide, Coil

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        tools:srcCompat="@tools:sample/avatars" />

Picasso

Code

Picasso.with(this).load("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png").into(imageView)

Result

Picasso

Glide

Code

Glide.with(this).load("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png").into(imageView)

Result

Glide

Coil

Code

imageView.load("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png")

Result

Coil

@fernandospr You can work around this by setting the scaleType to centerCrop or scale(Scale.FILL) on your request.

This occurs because wrap_content is evaluated to 1px whereas Glide and Picasso treat it as the height of the parent. I'm working on fixing this behaviour for 0.7.0.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cioccarellia picture cioccarellia  路  3Comments

GeniusRUS picture GeniusRUS  路  4Comments

RubenGonzalezGonzalez picture RubenGonzalezGonzalez  路  6Comments

SourabhSNath picture SourabhSNath  路  3Comments

theScrabi picture theScrabi  路  5Comments