How to scale an Image in ImageView to keep the aspect ratio
Asked Answered
H

26

594

In Android, I defined an ImageView's layout_width to be fill_parent (which takes up the full width of the phone).

If the image I put to ImageView is bigger than the layout_width, Android will scale it, right? But what about the height? When Android scales the image, will it keep the aspect ratio?

What I find out is that there is some white space at the top and bottom of the ImageView when Android scales an image which is bigger than the ImageView. Is that true? If yes, how can I eliminate that white space?

Hauge answered 26/3, 2010 at 8:41 Comment(0)
S
893
  1. Yes, by default Android will scale your image down to fit the ImageView, maintaining the aspect ratio. However, make sure you're setting the image to the ImageView using android:src="..." rather than android:background="...". src= makes it scale the image maintaining aspect ratio, but background= makes it scale and distort the image to make it fit exactly to the size of the ImageView. (You can use a background and a source at the same time though, which can be useful for things like displaying a frame around the main image, using just one ImageView.)

  2. You should also see android:adjustViewBounds to make the ImageView resize itself to fit the rescaled image. For example, if you have a rectangular image in what would normally be a square ImageView, adjustViewBounds=true will make it resize the ImageView to be rectangular as well. This then affects how other Views are laid out around the ImageView.

    Then as Samuh wrote, you can change the way it default scales images using the android:scaleType parameter. By the way, the easiest way to discover how this works would simply have been to experiment a bit yourself! Just remember to look at the layouts in the emulator itself (or an actual phone) as the preview in Eclipse is usually wrong.

Susannasusannah answered 26/3, 2010 at 15:7 Comment(13)
Thanks. But what if I have an ImageView, and I set the image by using imageView.setImageBitmap()?Hauge
That's the same thing, just done in code rather than XML. setImageBitmap is the same as android:src="..." and setBackground... is android:background="..."Susannasusannah
@SteveHaley i know it is too late but can you please tell me image.setImageDrawable equivalent in xml codePentagrid
@SuperUser image.setImageDrawable(...) is android:src="..." in xml aswell.Volsung
"android:adjustViewBounds" is the handy one here to note! if you do not add this, you most likely will have issues with the ImageView border/bounds/container not scaling correctly.Rodmann
<code>android:scaleType="fitCenter"</code> Also seem to work well. It automatically crops such that image fully fits the Image view.Pounds
Be aware that adjustViewBounds would not work in case ImageView has exact size specified in layout #16023341Morn
Spot on ! Brilliant answer ...saved a lot of coding...i was going for a custom imageview..thanks a lot !Sashenka
It's awesome! I find your answer for along time. Before that I used adjustViewBounds and setBackground, It wasn't working as well.Residuary
src= vs background= was the difference for me!Maltreat
android:adjustViewBounds was the last piece to my puzzle, thanks!Parkland
Correct answer but I withheld my +1 because IMO your verbosity was unwarranted for this question. Regardless, thank you for your time.Tucci
android:adjustViewBounds="true" finally fixed it for me. Thanks.Uracil
L
314

See android:adjustViewBounds.

Set this to true if you want the ImageView to adjust its bounds to preserve the aspect ratio of its drawable.

Loeffler answered 8/7, 2010 at 12:8 Comment(5)
This is the correct fix for the issue. We were having this on our image view, where the height included all of this extra whitespace. It isn't "transparent pixels", since we had fill_parent for width, and wrap_content for height. If you don't have adjustViewBounds=true, then you get the extra whitespace. After setting that to true, our issue went away. Thanks!Paz
thanks, this and setting it to src instead of background worked perfectly!Fielding
See also how-to-scale-bitmap-to-screen-sizeSuccory
This is the perfect fix for the issue. Also for the sizes, use the parent container to set the size, and set match_parent in the ImageView. This solves a lot of troubles.Convexity
+1 for getting to the point. I initially wrote that in a more "colloquial" phrase and sof barred me from submitting it. Rather than ruffle feathers a went PC.Tucci
B
210

To anyone else having this particular issue. You have an ImageView that you want to have a width of fill_parent and a height scaled proportionately:

Add these two attributes to your ImageView:

android:adjustViewBounds="true"
android:scaleType="centerCrop"

And set the ImageView width to fill_parent and height to wrap_content.

Also, if you don't want your image to be cropped, try this:

 android:adjustViewBounds="true"
 android:layout_centerInParent="true"
Bruges answered 26/5, 2011 at 18:45 Comment(6)
Yes but your image gets cropped. The perfect solution would stretch to width, maintain aspect ratio and not crop. I have no idea why this has to be so anoing to do...Pinole
Me either :( Sorry if my solution did not help you, but it did help me.Bruges
Kevin, what you said was exactly what i was looking for, if the size of the image is less than that of the screen, it gets zoomed in and centered, perfect. Thanks.Hendry
+1, except for "(or other View)". AFAICT no other view has adjustViewBounds or scaleType attributes.Poucher
how about using android:scaleType="centerInside" instead of android:scaleType="centerCrop"? It would also not crop the image but ensure that both width and height are less than or equal the imageview's width and height :) Here's a good visual guide for scaletypes: thoughtbot.com/blog/android-imageview-scaletype-a-visual-guideAlcantar
@Alcantar I looked through all of these and other questions, and this was the solution that worked for me. It involved no converting and worked perfectly.Bola
B
59

If you want an ImageView that both scales up and down while keeping the proper aspect ratio, add this to your XML:

android:adjustViewBounds="true"
android:scaleType="fitCenter"

Add this to your code:

// We need to adjust the height if the width of the bitmap is
// smaller than the view width, otherwise the image will be boxed.
final double viewWidthToBitmapWidthRatio = (double)image.getWidth() / (double)bitmap.getWidth();
image.getLayoutParams().height = (int) (bitmap.getHeight() * viewWidthToBitmapWidthRatio);

It took me a while to get this working, but this appears to work in the cases both where the image is smaller than the screen width and larger than the screen width, and it does not box the image.

Barns answered 18/3, 2012 at 18:39 Comment(5)
Why not just use android:scaleType="centerCrop"?Consubstantiate
works like a charm, thanks. scaleType depend on situation, for example i needed exactly this.Cradling
This's a little bit barbarian way of resizing the view. What happens if the view bounds change after you set the bitmap to the ImageView? This's why it should be done in onMeasure(), which can be implemented if you make a custom subclass of ImageView.Inclinometer
All I needed was the fitCenter and adjustViewBounds, the rest of the code at least for me was unnecessaryMarji
This works for me and don't need to add any code. Without the adjustViewBounds if the image width was smaller than imageView width, it was not scaling up, so the height was stopping to the native height and on the width some bands did appear.Kurman
T
18

This worked for me:

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="39dip"
android:scaleType="centerCrop"
android:adjustViewBounds ="true"
Thurber answered 28/3, 2013 at 10:31 Comment(0)
S
12

This is how it worked for me inside a ConstraintLayout:

<ImageView
    android:id="@+id/myImg"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true"/>

Then in code, I set the drawable as:

ImageView imgView = findViewById(R.id.myImg);
imgView.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.image_to_show, null));

This fits the image nicely according to its aspect ratio and keeps it in centre.

Spillway answered 11/6, 2019 at 10:27 Comment(0)
T
11

this solved my problem

android:adjustViewBounds="true"
android:scaleType="fitXY"
Technique answered 24/4, 2017 at 11:30 Comment(1)
It doesn't preserve the aspect ratio of the image for me.Enumerate
F
9

Take a look at ImageView.ScaleType to control and understand the way resizing happens in an ImageView. When the image is resized (while maintaining its aspect ratio), chances are that either the image's height or width becomes smaller than ImageView's dimensions.

Flunk answered 26/3, 2010 at 9:9 Comment(0)
G
9

Below code Working for scale image as aspect ratio:

Bitmap bitmapImage = BitmapFactory.decodeFile("Your path");
int nh = (int) ( bitmapImage.getHeight() * (512.0 / bitmapImage.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(bitmapImage, 512, nh, true);
your_imageview.setImageBitmap(scaled);
Glucose answered 12/9, 2014 at 12:23 Comment(0)
M
7

Use these properties in ImageView to keep aspect ratio:

android:adjustViewBounds="true"
android:scaleType="fitXY"

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    />
Meadows answered 5/5, 2016 at 6:29 Comment(1)
Only this answer helped me. Thanks!Enumerate
G
6

I have an image smaller than the screen. To have it stretched proportionally to the max and centered in the view I had to use the following code:

<ImageView
    android:id="@+id/my_image"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:adjustViewBounds="true"
    android:layout_weight="1"
    android:scaleType="fitCenter" />

Have in mind though, that if you have a relative layout and have some elements set to be above or below the ImageView, they will be most likely overlapped by the image.

Gilman answered 2/10, 2012 at 16:12 Comment(0)
U
5

If image quality decreases in: use

android:adjustViewBounds="true"

instead of

android:adjustViewBounds="true"
android:scaleType="fitXY"
Uncinus answered 20/12, 2018 at 6:9 Comment(0)
K
3

For anyone of you who wants the image to fit exact the imageview with proper scaling and no cropping use

imageView.setScaleType(ScaleType.FIT_XY);

where imageView is the view representing your ImageView

Kreda answered 10/12, 2012 at 12:14 Comment(3)
Nope, this changes the aspect ration. The docs say: "Scale in X and Y independently, so that src matches dst exactly. This may change the aspect ratio of the src."Fay
By the way, this FIT_XY can not be used for changing the width/height of the image for displaying on the imageview.Periodate
ScaleType.FIT_XY does not preserve the aspect ratio. ScaleType.FIT_XY will stretch the image to exactly fit the ImageView dimensions.Wilkie
B
3

You can calculate screen width. And you can scale bitmap.

 public static float getScreenWidth(Activity activity) {
        Display display = activity.getWindowManager().getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        display.getMetrics(outMetrics);
        float pxWidth = outMetrics.widthPixels;
        return pxWidth;
    }

calculate screen width and scaled image height by screen width.

float screenWidth=getScreenWidth(act)
  float newHeight = screenWidth;
  if (bitmap.getWidth() != 0 && bitmap.getHeight() != 0) {
     newHeight = (screenWidth * bitmap.getHeight()) / bitmap.getWidth();
  }

After you can scale bitmap.

Bitmap scaledBitmap=Bitmap.createScaledBitmap(bitmap, (int) screenWidth, (int) newHeight, true);
Butyraceous answered 10/3, 2015 at 12:36 Comment(0)
F
3

When doing this programmatically, be sure to call the setters in the correct order:

imageView.setAdjustViewBounds(true)
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP)
Footed answered 6/4, 2017 at 19:39 Comment(0)
L
2

If you want your image occupy the maximum possible space then the best option would be

android:layout_weight="1"
android:scaleType="fitCenter"
Lophobranch answered 19/8, 2012 at 15:33 Comment(0)
L
2

Yo don't need any java code. You just have to :

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />

The key is in the match parent for width and height

Linguini answered 17/1, 2017 at 2:15 Comment(0)
B
1

I use this:

<ImageView
android:id="@+id/logo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"
android:scaleType="centerInside"
android:src="@drawable/logo" />
Bedraggled answered 26/6, 2013 at 16:7 Comment(1)
I also set android:adjustViewBounds="true". centerInside was the way to go to prevent cropping and maintaining the aspect ratio.Doily
R
1

Try using android:layout_gravity for ImageView:

android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_weight="1"

The example above worked for me.

Reportorial answered 20/8, 2013 at 13:11 Comment(1)
android:layout_weight="1" is the key.Waiter
O
1

I have an algorithm to scale a bitmap to bestFit the container dimensions, maintaining its aspect ratio. Please find my solution here

Hope this helps someone down the lane!

Oto answered 8/4, 2014 at 8:29 Comment(0)
T
1

Pass your ImageView and based on screen height and width you can make it

    public void setScaleImage(EventAssetValueListenerView view){
        // Get the ImageView and its bitmap
        Drawable drawing = view.getDrawable();
        Bitmap bitmap = ((BitmapDrawable)drawing).getBitmap();
        // Get current dimensions
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        float xScale = ((float) 4) / width;
        float yScale = ((float) 4) / height;
        float scale = (xScale <= yScale) ? xScale : yScale;

        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);

        Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        BitmapDrawable result = new BitmapDrawable(scaledBitmap);
        width = scaledBitmap.getWidth();
        height = scaledBitmap.getHeight();

        view.setImageDrawable(result);

        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
        params.width = width;
        params.height = height;
        view.setLayoutParams(params);
    }

Theurich answered 4/1, 2016 at 13:24 Comment(0)
A
1

Programatically apply aspect ratio to Imageview:

aspectRatio = imageWidth/imageHeight   
ratioOfWidth = imageWidth/maxWidth  
ratioOfHeight = imageHeight/maxHeight  


if(ratioOfWidth > ratioOfHeight){​​​​​​​
    imageWidth = maxWidth 
    imageHeight = imageWidth/aspectRatio
}​​​​​​​ else if(ratioOfHeight > ratioOfWidth){​​​​​​​
    imageHeight = maxHeight
    imageWidth = imageHeight * aspectRatio
}​​​​​​​

After that you can use scaled bitmap to image view

Bitmap scaledBitmap= Bitmap.createScaledBitmap(bitmap, (int) imageWidth , (int) imageHeight , true);
Anabasis answered 1/12, 2020 at 12:15 Comment(0)
S
0

in case of using cardviewfor rounding imageview and fixed android:layout_height for header this worked for me to load image with Glide

    <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="220dp"
             xmlns:card_view="http://schemas.android.com/apk/res-auto"
             >

    <android.support.v7.widget.CardView
            android:id="@+id/card_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center|top"
            card_view:cardBackgroundColor="@color/colorPrimary"
            card_view:cardCornerRadius="10dp"
            card_view:cardElevation="10dp"
            card_view:cardPreventCornerOverlap="false"
            card_view:cardUseCompatPadding="true">

        <ImageView
                android:adjustViewBounds="true"
                android:maxHeight="220dp"
                android:id="@+id/iv_full"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:scaleType="fitCenter"/>

    </android.support.v7.widget.CardView>
</FrameLayout>
Stockholm answered 7/11, 2018 at 20:23 Comment(0)
F
0

You can scale image that will also reduce the size of your image. There is a library for it you can download and use it. https://github.com/niraj124124/Images-Files-scale-and-compress.git

How to use 1)Import the compressor-v1.0. jar to your project. 2)Add the below sample code to test. ResizeLimiter resize = ImageResizer.build(); resize.scale("inputImagePath", "outputImagePath",imageWidth, imageHeight); Many more methods are there according to your requirement

Friedland answered 29/1, 2019 at 20:16 Comment(0)
B
0

Quick answer:

<ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="center"
        android:src="@drawable/yourImage"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
Boschbok answered 1/3, 2020 at 17:3 Comment(0)
N
-5
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 130, 110, false));
Namtar answered 24/8, 2013 at 9:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.