Skip to content Skip to sidebar Skip to footer

Scale Image Keeping Its Aspect Ratio In Background Drawable

How do I make a background image fit the view but keep its aspect ratio when using as a background drawable XML? None of 's android:gravity values gi

Solution 1:

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:

    <RelativeLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent" ><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/backgrnd"android:scaleType="centerCrop" />
    
        ...
    
        rest layout components here
    
        ...
    
    </RelativeLayout>

Solution 2:

There is an easy way to do this from the drawable:

your_drawable.xml

<?xml version="1.0" encoding="utf-8"?><layer-listxmlns:android="http://schemas.android.com/apk/res/android" ><itemandroid:drawable="@color/bg_color"/><item><bitmapandroid: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.

Solution 3:

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

publicclassCustomBackgroundDrawableextendsDrawable
{
    privateRectmTempRect=newRect();
    privatePaintmBitmapPaint=newPaint(Paint.ANTI_ALIAS_FLAG);

    ...

publicvoiddraw(@NonNull Canvas canvas)
{
    Rectbounds= 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) {
                floatscale= Math.min(mBitmap.getWidth()/(float)bounds.width(), mBitmap.getHeight()/(float)bounds.height());

                floatbitmapVisibleWidth= scale * bounds.width();
                floatbitmapVisibleHeight= scale * bounds.height();

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

                floatbitmapScaledWidth= scale * mBitmap.getWidth();
                floatbitmapScaledHeight= scale * mBitmap.getHeight();
                intcenterPadding= (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

Solution 4:

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.

Solution 5:

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.

<bitmapxmlns: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.

Post a Comment for "Scale Image Keeping Its Aspect Ratio In Background Drawable"