Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make an Image as large as possible while maintaining aspect ratio

I have an image which is smaller than the container I would like it to fit inside of. I would like the image to stretch, keeping it's aspect ratio, to it's largest possible size.

To illustrate this problem:

<ImageView  android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/thumbnail"
            android:scaleType="fitXY"
            android:adjustViewBounds="true"/>

The ImageView above would be stretched to fill the width of the container. The @drawable it contained would also stretch along the x axis to fit the width of ImageView which is perfect. The problem however is that the dimension labelled wrap_content, in this case height, remains the same size as the @drawables initial height.

I have read the documentation regarding ScaleType here and can't find the answer there.

The following image describes the above code:

enter image description hereenter image description here

  Current behaviour               Desired Behaviour

Edit

An ImageView given scaleType="fitCenter" will accurately expand/shrink the @drawable inside of it to grow as large as possible while retaining it's aspect ratio.

The ImageViews dimensions are defined before the @drawable is scaled in any way. The ImageView dimensions are not effected by scaling of it's contained @drawable.

like image 434
Graeme Avatar asked Sep 20 '11 14:09

Graeme


People also ask

How do you maintain aspect ratio?

In the CSS for the <div>, add a percentage value for padding-bottom and set the position to relative, this will maintain the aspect ratio of the container. The value of the padding determines the aspect ratio. ie 56.25% = 16:9.

How do I constrain image size in CSS?

What if our image needs to be limited to the width of a parent element? In that situation we can use CSS max-width or width to fit the image. Use max-width: 100% to limit the size but allow smaller image sizes, use width: 100% to always scale the image to fit the parent container width.

Why is it important to maintain aspect ratios when resizing an image?

When scaling your image, it's crucial to maintain the ratio of width to height, known as aspect ratio, so it doesn't end up stretched or warped. If you need a specific width and height, you may need a mixture of resizing and cropping to get the desired result.


2 Answers

XML

The only solution to this in XML is to use "match_parent" or a discrete maximum value instead of "wrap_content" where possible. This will ensure the ImageView is the correct size, which will then meaning adding scaleType="fitCenter" will ensure the @drawable will then scale correctly.

Programatically

It's ugly, but you can resize the ImageView after it's dimensions have been given discrete values:

    final ImageView thumbnailView = (ImageView) toReturn.findViewById(R.id.thumbnail);  

    ViewTreeObserver thumbnailViewVto = thumbnailView.getViewTreeObserver();
    thumbnailViewVto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        private boolean changed = false;
        @Override
        public void onGlobalLayout() {
            if(!changed) {
                Drawable image = getResources().getDrawable(R.drawable.thumbnail);
                float heighToWidthRatio = image.getIntrinsicWidth()/image.getIntrinsicHeight();
                int height = thumbnailView.getHeight();

                thumbnailView.setLayoutParams(
                        new LayoutParams(
                                (int) (height * heighToWidthRatio), height));
                changed = true;
            }
        }
    });

EDIT

    final ImageView thumbnailView = (ImageView) toReturn.findViewById(R.id.thumbnail);  

    thumbnailView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            // Remove the GlobalOnLayout Listener so it only fires once.
            thumbnailView.getViewTreeObserver().removeGlobalOnLayoutListener(this)

            // Find the images Height to Width ratio
            Drawable image = getResources().getDrawable(R.drawable.thumbnail);
            float heighToWidthRatio = image.getIntrinsicWidth()/image.getIntrinsicHeight();

            // Use this ratio to discover the ratio of the ImageView to allow it to perfectly contain the image.
            int height = thumbnailView.getHeight();
            thumbnailView.setLayoutParams(new LayoutParams(
                                (int) (height * heighToWidthRatio), height));
        }
    });
like image 154
Graeme Avatar answered Oct 08 '22 00:10

Graeme


Looks like you want fitCenter, which uses Matrix.ScaleToFit CENTER.

like image 23
mbeckish Avatar answered Oct 08 '22 00:10

mbeckish