How to align ImageView from below, fill its width and height and keep aspect ratio?

Background

There are various XML attributes for ImageView to scale its contents and various layouts that allow you to place views and set their sizes.

However, I cannot figure out how to scale the image well in some cases.

An example of this is placing the ImageView at the bottom (for example, frameLayout), scaling its width as large as possible and preserving the aspect ratio (without cropping).

Problem

None of the combinations found work, including various ScaleType, adjustViewBounds, gravity, ...

ImageView seems to be missing some important ScaleType values.

What i tried

So far, the only solution that worked for me is to set the image at the bottom (using gravity in the lower and central horizontal) and use a code similar to this:

final ImageView logoBackgroundImageView = ...; final LayoutParams layoutParams = logoBackgroundImageView.getLayoutParams(); final Options bitmapOptions = ImageService.getBitmapOptions(getResources(), R.drawable.splash_logo); final int screenWidth = getResources().getDisplayMetrics().widthPixels; layoutParams.height = bitmapOptions.outHeight * screenWidth / bitmapOptions.outWidth; logoBackgroundImageView.setLayoutParams(layoutParams); 

This usually works and does not need big changes to make it work when it is not in full screen, but I am wondering if there is an easier way.

Perhaps this will not work if the height is too high, so you can change it so that in case this happens, you will set the width to a smaller size so that everything fits the container.

Question

Is there a solution or library that fixes various problems with ImageView?


EDIT: here is an example image of what I'm trying to do, this time, within the vertical LinearLayout, which borders the ImageView in the middle between two other views:

enter image description here

As you can see, in some (or all?) Previews, the average image is aligned to the right, and does not remain in the middle (horizontally).

I want him to take all the space that he got and scale it (keeping the proportions), but still aligned to the bottom of the space that he has.

here is a sample XML of one combination that I tried:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FF339AE2"> <View android:layout_width="match_parent" android:id="@+id/topView" android:layout_alignParentTop="true" android:layout_height="100dp" android:background="#FF00ff00" /> <FrameLayout android:layout_below="@+id/topView" android:layout_width="match_parent" android:layout_centerHorizontal="true" android:layout_above="@+id/bottomView" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:background="#FFffff00" android:layout_gravity="bottom|center_horizontal" android:src="@android:drawable/sym_def_app_icon" android:scaleType="fitEnd" android:layout_height="match_parent" /> </FrameLayout> <View android:background="#FFff0000" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:id="@+id/bottomView" android:layout_width="match_parent" android:layout_height="100dp"/> </RelativeLayout> 

Note again that I tried several combinations, but none of them worked, so if you suggest changing something in XML, try it first. Also note that the above POC value (to make it easy to read).

By the way, the workaround that I suggested works in some (or most?) Cases, but not in all. You can notice this by simply turning the device. Perhaps there is a way to fix it or extend it from ImageView to provide an extra case.

+8
android aspect-ratio imageview
source share
6 answers

You need a combination of three attributes:

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

The adjustViewBounds attribute adjustViewBounds necessary because the ImageView measures itself to match the original default sizes, regardless of the scale performed according to the type of scale.

+14
source share

You can use custom FitWidthAtBottomImageView to achieve this code:

 public class FitWidthAtBottomImageView extends ImageView { public FitWidthAtBottomImageView(Context context) { super(context); } public FitWidthAtBottomImageView(Context context, AttributeSet attrs) { super(context, attrs); } public FitWidthAtBottomImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public FitWidthAtBottomImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void onDraw(Canvas canvas) { int i = getWidth() - getPaddingLeft() - getPaddingRight(); int j = getHeight() - getPaddingTop() - getPaddingBottom(); if (getBackground() != null) { getBackground().draw(canvas); } if (getDrawable() != null && getDrawable() instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable) getDrawable()).getBitmap(); int h = bitmap.getHeight() * i / bitmap.getWidth(); canvas.drawBitmap(bitmap, null, new RectF(getPaddingLeft(), getPaddingTop() + j - h, getPaddingLeft() + i, getHeight() - getPaddingBottom()), null); } else { super.onDraw(canvas); } } } 

manually draw the bottom aligned image you want.

+6
source share

this is a custom ImageView based on om proof, you will need to add the missing constructors and do the Matrix setup when the ImageView Drawable changes:

 class V extends ImageView { public V(Context context) { super(context); setScaleType(ScaleType.MATRIX); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); Drawable d = getDrawable(); if (d != null) { Matrix matrix = new Matrix(); RectF src = new RectF(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); RectF dst = new RectF(0, 0, w, h); matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER); float[] points = { 0, d.getIntrinsicHeight() }; matrix.mapPoints(points); matrix.postTranslate(0, h - points[1]); setImageMatrix(matrix); } } } 

how it works shorter:

  • the matrix is ​​first set by calling Matrix.setRectToRect() using stf == Matrix.ScaleToFit.CENTER , the result will be the same as ImageView.ScaleType.FIT_CENTER

  • then to align Drawable to the bottom of Matrix.mapPoints() , it is called, it displays the Drawable left / bottom corner, and the result is converted to a point, as shown in ImageView

  • and finally Matrix.postTranslate() translates the MAtrix along the Y axis to the bottom of the ImageView

+1
source share

Try using android:scaleType="fitCenter"

Edit

Hm, I understand what you mean, another option is to have it fitEnd on the xml portrait and create an identical xml in the layout-earth folder (if necessary, create it) using android:scaleType="fitCenter" , which will be used on the landscape only

0
source share

I used android: scaleType = "fitXY", but it made me try it so many times until the image fit in the XY of the whole screen, which I mean there is a strange error in scaleType and fitEnd will work fine, but you need to will delete it and write again until it comes to the end of any screen without corpping. The bottom line of scaleType has errors and errors until it gives you what you need.

-one
source share

Fist of all, I really do not understand what you really want to align the image from below from what I read in your layout. My layout will center the image, and you can scale the view below to see how the image will look. Change the height of the top or bottom view, the image size will increase or decrease depending on the space available for the image.

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <View android:id="@+id/topView" android:layout_width="match_parent" android:layout_height="100dp" android:layout_alignParentTop="true" android:background="#FF00ff00" /> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/bottomView" android:layout_below="@+id/topView"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_horizontal" android:background="#FFffff00" android:scaleType="fitCenter" android:src="@android:drawable/sym_def_app_icon" /> </FrameLayout> <View android:id="@+id/bottomView" android:layout_width="match_parent" android:layout_height="100dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:background="#FFff0000" /> </RelativeLayout> 

Hope this fixes your issue.

-one
source share

All Articles