Как сделать фоновое изображение подходящим для представления, но сохранить его соотношение сторон при использовании <bitmap />
в качестве фонового рисунка xml?
Ни один из значений <bitmap>
android:gravity
не дает желаемого эффекта.
Масштабировать изображение, сохраняя его соотношение сторон в фоновом режиме
Ответ 1
Невозможно добиться манипулирования фоновым атрибутом только в xml файлах. Существует два варианта:
-
Вы сокращаете или масштабируете растровое изображение программно с помощью
Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
и установите его как некоторый фонView
. -
Вы используете
ImageView
вместо фона, помещая его в качестве первого элемента макета и укажите для негоandroid:scaleType
:<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>
Ответ 2
Существует простой способ сделать это из 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>
Единственным недостатком является то, что если места недостаточно, ваше изображение не будет отображаться полностью, но оно будет обрезано, я не смог бы найти способ сделать это прямо из drawable. Но из тестов я сделал это очень хорошо, и это не зациклирует большую часть изображения. Вы можете играть больше с параметрами гравитации.
Другой способ - просто создать макет, где вы будете использовать ImageView
и установите scaleType
на fitCenter
.
Надеемся, что эта информация поможет вам достичь желаемого.
Ответ 3
Другим подходом было бы создать патч 9 изображений вашего обычного изображения и растянуть масштаб так, как вы этого хотите.
Вы могли бы сосредоточить его на содержании, поместив 9-патч-точки в углах, которые сохранят ваше соотношение (если внешний край вашего изображения будет повторяемым/прозрачным).
Надеюсь, вы получите эту идею.
Ответ 4
Использование метода, описанного a.ch, отлично подойдет для меня, за исключением того, что я использовал этот тип шкалы, который работал намного лучше для того, что мне было нужно:
android:scaleType="centerCrop"
Вот полный список доступных типов шкалы: http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
Ответ 5
Попробуйте использовать InsetDrawable (хорошо работает для меня).
Просто отрисуйте эту выбируемую и вставку (или прописку), которую вы хотите с любой из четырех сторон.
InsetDrawable insetDrawable = new InsetDrawable(drawable, insetLeft, insetTop, insetRight, insetBottom);
Он специально используется для настройки фонового рисунка, размера меньшего размера или вида.
См. здесь: https://developer.android.com/reference/android/graphics/drawable/InsetDrawable.html
Ответ 6
Старый вопрос, но ни один из других ответов не работал у меня. Однако этот xml-код:
<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>
Ответ 7
Если ваш растровый рисунок шире, чем высокий, используйте android:gravity="fill_vertical"
. В противном случае используйте android:gravity="fill_horitzonal"
. Это похоже на использование android:scaleType="centerCrop"
на ImageView
.
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="fill_vertical"
android:src="@drawable/image" />
Если вы поддерживаете несколько ориентаций, вы можете создать один растровый XML файл в папке drawable-port
, а другой в папке drawable-land
.
Ответ 8
Я хотел сделать что-то подобное в моем классе Drawable. Вот важные части:
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);
}
}
}
}
При таком подходе вы гибки, чтобы применять любую требуемую шкалу.