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
.
How to scale an Image in ImageView to keep the aspect ratio
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 thanandroid:background="..."
.src=
makes it scale the image maintaining aspect ratio, butbackground=
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.)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.
how to fit image to width and keep the aspect ratio in android
first in your layout add
android:scaleType="matrix"
to your imageView.
then in your java code add this:
ackground.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Bitmap backgroundBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.background_image);
float imageRatio = (float) backgroundBitmap.getWidth() / (float) backgroundBitmap.getHeight();
int imageViewWidth = background.getWidth();
int imageRealHeight = (int) (imageViewWidth / imageRatio);
Bitmap imageToShow = Bitmap.createScaledBitmap(backgroundBitmap, imageViewWidth, imageRealHeight, true);
background.setImageBitmap(imageToShow);
}
});
I will break it down for you:
at the java code you create a Bitmap object with the desired width (your imageView width) and set it to your imageView. but you need to make your imageView scaleType to matrix to prevent android from automatically scaling it!
Fit image into ImageView, keep aspect ratio and then resize ImageView to image dimensions?
(The answer was heavily modified after clarifications to the original question)
After clarifications:
This cannot be done in xml only. It is not possible to scale both the image and the ImageView
so that image's one dimension would always be 250dp and the ImageView
would have the same dimensions as the image.
This code scales Drawable
of an ImageView
to stay in a square like 250dp x 250dp with one dimension exactly 250dp and keeping the aspect ratio. Then the ImageView
is resized to match the dimensions of the scaled image. The code is used in an activity. I tested it via button click handler.
Enjoy. :)
private void scaleImage(ImageView view) throws NoSuchElementException {
// Get bitmap from the the ImageView.
Bitmap bitmap = null;
try {
Drawable drawing = view.getDrawable();
bitmap = ((BitmapDrawable) drawing).getBitmap();
} catch (NullPointerException e) {
throw new NoSuchElementException("No drawable on given view");
} catch (ClassCastException e) {
// Check bitmap is Ion drawable
bitmap = Ion.with(view).getBitmap();
}
// Get current dimensions AND the desired bounding box
int width = 0;
try {
width = bitmap.getWidth();
} catch (NullPointerException e) {
throw new NoSuchElementException("Can't find bitmap on given view/drawable");
}
int height = bitmap.getHeight();
int bounding = dpToPx(250);
Log.i("Test", "original width = " + Integer.toString(width));
Log.i("Test", "original height = " + Integer.toString(height));
Log.i("Test", "bounding = " + Integer.toString(bounding));
// Determine how much to scale: the dimension requiring less scaling is
// closer to the its side. This way the image always stays inside your
// bounding box AND either x/y axis touches it.
float xScale = ((float) bounding) / width;
float yScale = ((float) bounding) / height;
float scale = (xScale <= yScale) ? xScale : yScale;
Log.i("Test", "xScale = " + Float.toString(xScale));
Log.i("Test", "yScale = " + Float.toString(yScale));
Log.i("Test", "scale = " + Float.toString(scale));
// Create a matrix for the scaling and add the scaling data
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
// Create a new bitmap and convert it to a format understood by the ImageView
Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
width = scaledBitmap.getWidth(); // re-use
height = scaledBitmap.getHeight(); // re-use
BitmapDrawable result = new BitmapDrawable(scaledBitmap);
Log.i("Test", "scaled width = " + Integer.toString(width));
Log.i("Test", "scaled height = " + Integer.toString(height));
// Apply the scaled bitmap
view.setImageDrawable(result);
// Now change ImageView's dimensions to match the scaled image
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
params.width = width;
params.height = height;
view.setLayoutParams(params);
Log.i("Test", "done");
}
private int dpToPx(int dp) {
float density = getApplicationContext().getResources().getDisplayMetrics().density;
return Math.round((float)dp * density);
}
The xml code for the ImageView
:
<ImageView a:id="@+id/image_box"
a:background="#ff0000"
a:src="@drawable/star"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_marginTop="20dp"
a:layout_gravity="center_horizontal"/>
Thanks to this discussion for the scaling code:
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html
UPDATE 7th, November 2012:
Added null pointer check as suggested in comments
Android Studio ImageView Change Only Width and Maintain Aspect Ratio
Take the set width and divide it by the aspect ratio to get the height then set it like the code below
Display display = requireActivity().getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
Resources r = getResources();
float density = getResources().getDisplayMetrics().density;
//float dpHeight = outMetrics.heightPixels / density;
float dpWidth = outMetrics.widthPixels / density;
int widthPX = Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, yourImageFixedWidthValue, r.getDisplayMetrics()));
float imageAspectRatio = (float) 335 / 217;
float imageWidth = widthPX;
float imageHeight = imageWidth / imageAspectRatio;
imageView.getLayoutParams().height = Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, imageHeight, r.getDisplayMetrics()));
imageView.setAdjustViewBounds(true);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
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
Related Topics
Android: How to Create a Dialog Without a Title
Display Fragment Viewpager Within a Fragment
How to Make an Application Ignore Screen Orientation Change
Fool-Proof Way to Handle Fragment on Orientation Change
Xamarin.Forms Listview: Set the Highlight Color of a Tapped Item
Is There a Better Way to Refresh Webview
Android Calendarview for Showing Events
What Does -Webkit-Text-Size-Adjust Do
How to Check the Internet Connection in Android
Add Ripple Effect to My Button with Button Background Color
Usb Device Access Pop-Up Suppression
What Is the Role of Content_Main.Xml in Android Studio 1.4
Android Activity Ondestroy() Is Not Always Called and If Called Only Part of the Code Is Executed
Android Eclipse Ddms - Can't Access Data/Data/ on Phone to Pull Files
Detect Scroll Up & Scroll Down in Listview