Android: How to Stretch an Image to the Screen Width While Maintaining Aspect Ratio

Android: How to stretch an image to the screen width while maintaining aspect ratio?

I accomplished this with a custom view. Set layout_width="fill_parent" and layout_height="wrap_content", and point it to the appropriate drawable:

public class Banner extends View {

private final Drawable logo;

public Banner(Context context) {
super(context);
logo = context.getResources().getDrawable(R.drawable.banner);
setBackgroundDrawable(logo);
}

public Banner(Context context, AttributeSet attrs) {
super(context, attrs);
logo = context.getResources().getDrawable(R.drawable.banner);
setBackgroundDrawable(logo);
}

public Banner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
logo = context.getResources().getDrawable(R.drawable.banner);
setBackgroundDrawable(logo);
}

@Override protected void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * logo.getIntrinsicHeight() / logo.getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}

How to maintain the aspect ratio of the image if imageview first stretch to fill parent

There can two possible workarounds even if you set the scale type fit_xy

1) 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.

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.

Android Stretch ImageView to fill width, maintain aspect ratio, align top

Well, fortunately android API provides another scaleType: matrix, So you are free to show parts of image you want, add these lines of code to onCreate method of the Activity :

    final ImageView iv = (ImageView) findViewById(R.id.iv);
iv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int viewWidth = iv.getMeasuredWidth();
int viewHeight = iv.getMeasuredHeight();
Drawable src = iv.getDrawable();
if (src != null) {
int srcWidth = src.getIntrinsicWidth();
int srcHeight = src.getIntrinsicHeight();
float wRatio = (float) viewWidth / srcWidth;
float hRatio = (float) viewHeight / srcHeight;
float scaleFactor = Math.max(wRatio, hRatio);
float hTranslate = (viewWidth - scaleFactor * srcWidth) / 2;
Matrix matrix = new Matrix();
matrix.setScale(scaleFactor, scaleFactor);
matrix.postTranslate(hTranslate, 0);
iv.setScaleType(ImageView.ScaleType.MATRIX);
iv.setImageMatrix(matrix);

Log.i("test", "srcWidth: " + srcWidth);
Log.i("test", "srcHeight: " + srcHeight);
Log.i("test", "viewWidth: " + viewWidth);
Log.i("test", "viewHeight: " + viewHeight);
Log.i("test", "wRatio: " + wRatio);
Log.i("test", "hRatio: " + hRatio);
Log.i("test", "scaleFactor: " + scaleFactor);
Log.i("test", "hTranslate: " + hTranslate);
}
iv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});

first you register an OnGlobalLayoutListener so you will access the dimension of the view in the right time (I believe you already know it), then you compute wRatio(width ratio) and hRatio(height ratio) using provided parameters and choose the bigger one as the scaleFactor (so you make sure that drawable covers whole of the view), Also you need to align drawable center horizontally (that's the role hTranslate plays), finally create the matrix and we're there!

Original image :

Sample Image

centerCrop result:

Sample Image

topCrop result (what we did by code)

Sample Image

Scale ImageView to fit screen width/height while maintaining aspect ratio

It turned out to be a bit hard, and not possible out of the box. Many have similar problems.

I ended up porting @patrick-boos solution to .Net like so:

Extended ImageView Class

using Android.Content;
using Android.Util;
using Android.Widget;

namespace Nsa.BigBrotherUtility.Helpers
{
/// <summary>
/// DynamicImageView is a helper extension that overrides OnMeasure in order to scale the said image
/// to fit the entire width/or height of the parent container.
/// </summary>
public class DynamicImageView : ImageView
{
public DynamicImageView(Context context, IAttributeSet attributeSet) : base(context, attributeSet)
{

}

protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = MeasureSpec.GetSize(widthMeasureSpec);
int height = width * Drawable.IntrinsicHeight / Drawable.IntrinsicWidth;
SetMeasuredDimension(width, height);
}

}
}

My axml

<Nsa.BigBrotherUtility.Helpers.DynamicImageView
android:id="@+id/overlayImageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
/>

The result

The 600x600 image now stretches to fill width of screen while maintaining aspect ratio

technical drawing being stretched to fit width of screen

android: stretch image in imageview to fit screen

to change pro-grammatically use :

imgview.setScaleType(ScaleType.FIT_XY);

OR

to change from xml use:

 android:scaleType="fitXY"

Stretch Image to Fit

I believe that is not possible, at least not with the options provided by scaleType attribute.

Your best option in this case is to use centerCrop, but only the center of the picture will be visible.

However, if you are not ok with this option, then you could scale the image programatically without loosing aspect ratio.
In order to achieve this you'll need to calculate a scale factor based on the screen width, and then use this scale factor to know the new height of the image.

Like this:

ImageView imageView = (ImageView)findViewById(R.id.imageView);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.foo);

int imageWidth = bitmap.getWidth();
int imageHeight = bitmap.getHeight();

int newWidth = getScreenWidth(); //this method should return the width of device screen.
float scaleFactor = (float)newWidth/(float)imageWidth;
int newHeight = (int)(imageHeight * scaleFactor);

bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
imageView.setImageBitmap(bitmap);

Also, you'll need to adjust the declaration of ImageView in layout file:

<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

Scale Image to fill ImageView width and keep aspect ratio

Without using any custom classes or libraries:

<ImageView
android:id="@id/img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />

scaleType="fitCenter" (default when omitted)

  • will make it as wide as the parent allows and up/down-scale as needed keeping aspect ratio.

scaleType="centerInside"

  • if the intrinsic width of src is smaller than parent width
    will center the image horizontally
  • if the intrinsic width of src is larger than parent width
    will make it as wide as the parent allows and down-scale keeping aspect ratio.

It doesn't matter if you use android:src or ImageView.setImage* methods and the key is probably the adjustViewBounds.



Related Topics



Leave a reply



Submit