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.
-
1Have you already tried [ScaleType](http://developer.android.com/reference/android/widget/ImageView.ScaleType.html)? – Chris Mar 27 '12 at 14:03
-
1Try android:scaleType="matrix" – Pavandroid Mar 27 '12 at 14:52
-
8ScaleType is for ImageView. Bitmaps do not support it. – OldSchool4664 Dec 01 '16 at 01:28
9 Answers
It is impossible to achieve manipulating background attribute within xml-files only. There are two options:
You cut/scale the bitmap programmatically with
Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
and set it as someView
's background.You use
ImageView
instead of background placing it as the first layout's element and specifyandroid: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>

- 8,285
- 5
- 40
- 53
-
3All possible `android:scaleType` values don't give the needed effect. An image fit the view keeping its aspect ratio only if I don't specify `scaleType` at all. – tilex Mar 28 '12 at 07:25
There is an easy way to do this from the drawable:
your_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@color/bg_color"/>
<item>
<bitmap
android:gravity="center|bottom|clip_vertical"
android:src="@drawable/your_image" />
</item>
</layer-list>
The only downside is that if there is not enough space, your image won't be fully shown, but it will be clipped, I couldn't find an way to do this directly from a drawable. But from the tests I did it works pretty well, and it doesn't clip that much of the image. You could play more with the gravity options.
Another way will be to just create an layout, where you will use an ImageView
and set the scaleType
to fitCenter
.
Hope this information helps you achieve what you want.

- 6,186
- 4
- 48
- 78
-
1This keeps the image unscaled and small and only displays it at the bottom. – J. Hesters Sep 06 '18 at 13:28
-
Indeed, if you need to scale it, other solutions are more appropriate. As you see, the properties do not refer to any type of scaling. – Ionut Negru Feb 25 '19 at 12:52
-
5
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

- 1,321
- 15
- 20
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.

- 13,202
- 6
- 48
- 76
If your bitmap is wider than it is tall, use android:gravity="fill_vertical"
. Otherwise, use android:gravity="fill_horizontal"
. This has a similar effect as using android:scaleType="centerCrop"
on an ImageView
.
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="fill_vertical"
android:src="@drawable/image" />
If you support multiple orientations, you can create one bitmap XML file in the drawable-port
folder and the other in the drawable-land
folder.

- 14,306
- 23
- 105
- 189

- 31,005
- 19
- 77
- 131
Using the method described by a.ch worked great for me except I used this scale type which worked much better for what I needed:
android:scaleType="centerCrop"
Here is a full list of available scale types: http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

- 440
- 3
- 14
-
1and here you can see some examples for each type: http://etcodehome.blogspot.de/2011/05/android-imageview-scaletype-samples.html – Father Stack Sep 27 '13 at 12:09
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

- 987
- 1
- 11
- 27
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>

- 2,589
- 3
- 23
- 30
In order to fit the image to the available space (or if you have set width and height in dp), I have tried the following approach, also 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
does the trick.

- 1,990
- 2
- 24
- 55