Android ImageView scale smaller image to width with flexible height without cropping or distortion

后端 未结 8 1927
面向向阳花
面向向阳花 2020-12-04 10:55

Often asked, never answered (at least not in a reproducible way).

I have an image view with an image that is smaller than the view. I want to scale

8条回答
  •  半阙折子戏
    2020-12-04 11:08

    This is a small addition to Mark Martinsson's excellent solution.

    If your image's width is larger than its height, then Mark's solution will leave space at the top and bottom of the screen.

    The below fixes this by first comparing the width and height: if the image width >= height, then it will scale the height to match the screen height, and then scale the width to preserve the aspect ratio. Similarly, if the image height > width, then it will scale the width to match the screen width and then scale the height to preserve the aspect ratio.

    In other words, it properly satisfies the definition of scaleType="centerCrop" :

    http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

    Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).

    package com.mypackage;
    
    import android.content.Context;
    import android.graphics.drawable.Drawable;
    import android.util.AttributeSet;
    import android.widget.ImageView;
    
    public class FixedCenterCrop extends ImageView
    {
        public FixedCenterCrop(final Context context, final AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
        {
            final Drawable d = this.getDrawable();
    
            if(d != null) {
                int height = MeasureSpec.getSize(heightMeasureSpec);
                int width = MeasureSpec.getSize(widthMeasureSpec);
    
                if(width >= height)
                    height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
                else
                    width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight());
    
                this.setMeasuredDimension(width, height);
    
            } else {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            }
        }
    }
    

    This solution automatically works in either portrait or landscape mode. You reference it in your layout just as you do in Mark's solution. E.g.:

    
    

提交回复
热议问题