Android ImageView adjusting parent's height and fitting width

AndroidResizeImageview

Android Problem Overview


Update : I solved this issue by using the method described in this answer

I'm a bit stuck with this issue, which I think should be pretty simple.

So my app downloads an image, and renders the bitmap in an ImageView, a child element of a RelativeLayout. I would like the ImageView to fit the parent width, and to adapt it's size to keep the aspect ratio.

Here is my XML :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout android:id="@+id/banner" android:layout_width="fill_parent" android:layout_height="wrap_content"></RelativeLayout>
<TextView  
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
android:text="@string/hello"
/>
</LinearLayout>

And the code :

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    
    RelativeLayout banner = (RelativeLayout) findViewById(R.id.banner);
    ImageView imgV = new ImageView(this);
    
    imgV.setScaleType(ImageView.ScaleType.CENTER_CROP);
    // I tried all the scale types : CENTER_INSIDE : same effect, FIT_CENTER : same effect... 
    
    imgV.setBackgroundColor(0x00FFFF00);

    imgV.setAdjustViewBounds(Color.BLUE);
    
     
    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
		 
    banner.addView(imgV,params);
   
    // Some code downloading the image stream
    
    bitmap = BitmapFactory.decodeStream(stream);
    
    
    imgV.setImageBitmap(bitmap);

    }

Desired :

Desired result

Result :

Current result

Android Solutions


Solution 1 - Android

Thanks to @Julien and @js. Here is complete solution of ImageView that will stretch bitmap height preserving aspect ratio even if bitmap is smaller than ImageView.

public class ResizableImageView extends ImageView {

    public ResizableImageView(Context context, AttributeSet attrs) {
	    super(context, attrs);
    }

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
         Drawable d = getDrawable();
	
         if(d!=null){
                 // ceil not round - avoid thin vertical gaps along the left/right edges
                 int width = MeasureSpec.getSize(widthMeasureSpec);
                 int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
                 setMeasuredDimension(width, height);
         }else{
                 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         }
    }

}

You can use this class in your xml layouts instead ImageView.

<com.example.ResizableImageView
    android:id="@+id/banner"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/banner" />

Solution 2 - Android

You're probably looking for android:adjustViewBounds="true" in xml or imageView.setAdjustViewBounds(true) in Java.

Solution 3 - Android

As I mentioned in a comment, I subclassed the ImageView. I found my code, here you go :

	protected class ResizableImageView extends ImageView
	{

		private Bitmap mBitmap;

		// Constructor

		public ResizableImageView(Context context)
		{
			super(context);
		}


		// Overriden methods

		
		  @Override 
		  protected void onMeasure(int widthMeasureSpec,
			      int heightMeasureSpec) {
			  if(mBitmap != null)
			  {
				    int width = MeasureSpec.getSize(widthMeasureSpec);
				    int height = width * mBitmap.getHeight() / mBitmap.getWidth();
				    setMeasuredDimension(width, height);

			  } 
			  else
			  {
				  super.onMeasure(widthMeasureSpec,
					      heightMeasureSpec);
			  }
			  }

			@Override
			public void setImageBitmap(Bitmap bitmap)
			{
				mBitmap = bitmap;
				 super.setImageBitmap(bitmap);
			}

	}

Solution 4 - Android

I think you should change your imgV width to "match_parent"

You should change the scale type to imgV.setScaleType(ImageView.ScaleType.CENTER_INSIDE);

Solution 5 - Android

I made a slight change to @Seraphim S's solution to account for cases where the image may be wide, and the view's bounds also wide (for example, rotating the device to landscape mode).

public class ResizableImageView extends ImageView {
    public ResizableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Drawable d = getDrawable();

        if (d != null) {

            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = MeasureSpec.getSize(heightMeasureSpec);

            if (width >= height) {
                width = (int) Math.ceil((float) height * (float) d.getIntrinsicWidth() / (float) d.getIntrinsicHeight());
            } else {
                height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
            }

            setMeasuredDimension(width, height);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJulienView Question on Stackoverflow
Solution 1 - AndroidSerafim SuhenkyView Answer on Stackoverflow
Solution 2 - AndroidMatthew WillisView Answer on Stackoverflow
Solution 3 - AndroidJulienView Answer on Stackoverflow
Solution 4 - Android2bardView Answer on Stackoverflow
Solution 5 - AndroidchuzView Answer on Stackoverflow