The device screen size has a weird effect when scaling ImageViews

Update: Screen sizes of several devices - red herring - the problem is that the image does not scale properly to fill the screen - see Comments on Ivan.

I have a layout file with one image:

<ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/image" android:layout_width="fill_parent" android:layout_height="wrap_content" android:adjustViewBounds="true" android:scaleType="centerCrop" /> 

Then I assign drawable, which is small and needs to be increased:

 setContentView(R.layout.image_story); ImageView image = (ImageView)findViewById(R.id.image); image.setImageDrawable(s.image); 

Here's how it displays on two AVDs with different screen sizes. They should be the same (detailed question below). Sorry for the large images.

using scaleType = centerCrop:

centered inside

AVDS:

Edit:

With layout_height = "fill_parent" and scaleType = "centerInside"

I have 2.1 AVD with default values, so the screen is smaller and it works exactly as expected - the image is scaled to fill the width, and the height of the view is wrapped in a scaled height.

On my Droid Bionic with a longer screen and on any AVD with the same screen size, this does not work - the image is scaled to fill the width, but the view is wrapped in the original strong> height of the preview image, so the top and bottom are cropped.

I have no idea why the aspect ratio of the device’s screen will affect this. I tried a myriad combination of layout options and scale types, trying to get this to work on Bionic. Everything works exactly as expected on a smaller screen, not a larger one. If I set the image height explicitly in dp , it works as expected, but I never know what the image (or screen) sizes will be. Any suggestions?

+6
source share
2 answers

This is a really very good question.

Here's the reason it behaves (from ImageView.onMeasure (int, int) [line 661] ):

 // Try adjusting height to be proportional to width if (!done && resizeHeight) { int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) + ptop + pbottom; if (newHeight <= heightSize) { // line 661 heightSize = newHeight; } // line 663 } 

What he does is to adjust the height of the view only if the new height based on the aspect ratio of the stretched and adjusted width (in our case, the exact width of the parent view) is less than the adjusted height (which in this view is simply popped native height plus gasket in our case. Let me know if you want me to stop this point further.)

I don’t understand why there is a restriction that the new height should be less. This only makes sense if our heightSize is either EXACTLY or AT_MOST and set to the upper bound. In other cases, this is not necessary for this.

So, instead of the whole fragment from 661 to 663, there should have been another call

 heightSize = resolveAdjustedSize(newHeight, mMaxHeight, heightSpec); 

to make sure that we are limited only by the height limit (i.e. we got the AT_MOST limit in heightSpec, and the height value in heightSpec is less than the new height. EXACTLY this cannot happen here if we do not use variable width.)

Maybe I missed something. Guys, whoever reads this, comment if you see any flaws , especially if you are part of the Android team at Google :)

PS . As a workaround, I can suggest you implement a custom ImageView and override onMeasure (int, int) to set the bounds of your exact aspect ratio. Let me know if you need help with the actual code.

UPD I'm going to write out names to attract the attention of smart Android guys on Google (I hope the guys have Google Alerts installed): Romain Guy, Roman Nurik, Reto Mayer, please take a look at this discussion.

+4
source

As I understand it, you need to scale the image while maintaining its aspect ratio. scaleType="fitCenter" should give you the desired behavior:

 <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/image" android:layout_width="fill_parent" android:layout_height="wrap_content" android:adjustViewBounds="true" android:scaleType="fitCenter" /> 

If this does not help, try adding this to the manifest file:

 <supports-screens android:resizeable="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" /> 
0
source

Source: https://habr.com/ru/post/908173/


All Articles