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 :
centerCrop result:
topCrop result (what we did by code)
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
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
Return a Value from Asynctask in Android
Ionic Build Android Error When Downloading Gradle
Execute Another Jar in a Java Program
Java Simpledateformat Always Returning January for Month
Spring Boot, Spring Data JPA with Multiple Datasources
Emulate Annotation Inheritance for Interfaces and Methods with Aspectj
When Exactly Do You Use the Volatile Keyword in Java
Convert Rgb Values to Color Name
Transitive Dependencies Not Resolved for Aar Library Using Gradle
Log4J Does Not Recreate Files on Deletion
Why Does Priorityqueue.Tostring Return the Wrong Element Order
Java' Is Not Recognized as an Internal or External Command
Rotating a Shape Vertically Around the X-Axis