Scale image keeping its aspect ratio in background

2019-01-16 23:08发布

How do I make a background image fit the view but keep its aspect ratio when using <bitmap /> as a background drawable XML? None of <bitmap>'s android:gravity values gives the desired effect.

9条回答
祖国的老花朵
2楼-- · 2019-01-16 23:13

I wanted to do something similar in my custom Drawable class. Here are the important pieces:

public class CustomBackgroundDrawable extends Drawable
{
    private Rect mTempRect = new Rect();
    private Paint mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    ...

public void draw(@NonNull Canvas canvas)
{
    Rect bounds = getBounds();
    if (mBitmap != null ) {
        if (mScaleType == ScaleType.SCALE_FILL) {
            //bitmap scales to fill the whole bounds area (bitmap can be cropped)
            if (bounds.height() > 0 && bounds.height() > 0) {
                float scale = Math.min(mBitmap.getWidth()/(float)bounds.width(), mBitmap.getHeight()/(float)bounds.height());

                float bitmapVisibleWidth = scale * bounds.width();
                float bitmapVisibleHeight = scale * bounds.height();

                mTempRect.set((int)(mBitmap.getWidth()-bitmapVisibleWidth)/2, 0, (int)(bitmapVisibleWidth+mBitmap.getWidth())/2, (int)bitmapVisibleHeight);
                canvas.drawBitmap(mBitmap, mTempRect, bounds, mBitmapPaint);
            }
        } else if (mScaleType == ScaleType.SCALE_FIT) {
            //bitmap scales to fit in bounds area
            if (bounds.height() > 0 && bounds.height() > 0) {
                float scale = Math.min((float)bounds.width()/mBitmap.getWidth(), (float)bounds.height()/mBitmap.getHeight());

                float bitmapScaledWidth = scale * mBitmap.getWidth();
                float bitmapScaledHeight = scale * mBitmap.getHeight();
                int centerPadding = (int)(bounds.width()-bitmapScaledWidth)/2;
                mTempRect.set(bounds.left + centerPadding, bounds.top, bounds.right - centerPadding, bounds.top+(int)bitmapScaledHeight);
                canvas.drawBitmap(mBitmap, null, mTempRect, mBitmapPaint);
            }
        }
    }
}

With this approach you are flexible to apply any scale logic that you need

查看更多
Root(大扎)
3楼-- · 2019-01-16 23:16

In order to fit the image to the available space (or if you have set width and height in dp), I have tried this approach if the image is not too wide.

Here I have set same width and height for square images [or you can wrap_content on both].

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_alignParentTop="true"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:src="@drawable/background_image"/> 

</RelativeLayout>

adjust view bounds and scale type center fit do the trick.

查看更多
\"骚年 ilove
4楼-- · 2019-01-16 23:22

Old question, but none of the other answers worked for me. This xml code did however:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:scaleType="centerCrop"
        android:src="@drawable/background_image"/> 

</RelativeLayout>
查看更多
Viruses.
5楼-- · 2019-01-16 23:23

Another approach would be to create patch 9 images of your regular image and have it stretch scale the way you want it to.

You could have it center the content by putting 9-patch-dots in the corners that will preserve your ratio obviously (assuming the outer most edge of your image is repeatable/transparent).

Hopefully you get the idea.

查看更多
贼婆χ
6楼-- · 2019-01-16 23:26

Try using InsetDrawable (worked well for me).

Just give this your drawable, and insets (or padding) you want from either of the four sides.

InsetDrawable insetDrawable = new InsetDrawable(drawable, insetLeft, insetTop, insetRight, insetBottom);

It is specifically used for setting background drawable, of size smaller or than the View.

See Here : https://developer.android.com/reference/android/graphics/drawable/InsetDrawable.html

查看更多
疯言疯语
7楼-- · 2019-01-16 23:28

It is impossible to achieve manipulating background attribute within xml-files only. There are two options:

  1. You cut/scale the bitmap programmatically with Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) and set it as some View's background.

  2. You use ImageView instead of background placing it as the first layout's element and specify android:scaleType attribute for it:

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
    
            android:src="@drawable/backgrnd"
            android:scaleType="centerCrop" />
    
        ...
    
        rest layout components here
    
        ...
    
    </RelativeLayout>
    
查看更多
登录 后发表回答