Масштабирование изображения с сохранением его соотношения сторон в фоновом режиме рисование
как сделать фоновое изображение в соответствии с видом, но сохранить его соотношение сторон при использовании <bitmap />
в качестве фона drawable XML?
Ни один из <bitmap>
' s android:gravity
значения дают желаемый эффект.
9 ответов:
невозможно добиться манипулирования атрибутом фона только в 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>
есть простой способ сделать это из 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
.надеюсь, что эта информация поможет вам достичь того, что вы хотите.
другой подход был бы создать патч 9 изображений вашего обычного изображения и растянуть масштаб так, как вы хотите.
вы можете центрировать контент, помещая 9-патч-точек в углах, которые будут явно сохранять ваше соотношение (предполагая, что внешний край вашего изображения повторяется/прозрачен).
надеюсь, вы поняли идею.
Я хотел сделать что-то подобное в моем пользовательском 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); } } } }
при таком подходе вы можете гибко применять любую логику масштабирования, которая вам нужна
используя метод, описанный a.ch работал отлично для меня, за исключением того, что я использовал этот тип шкалы, который работал намного лучше для того, что мне нужно:
android:scaleType="centerCrop"
вот полный список доступных типов масштаба: http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
попробуйте использовать InsetDrawable (хорошо для меня).
просто дайте это ваш drawable, и вставки (или обивка) вы хотите с любой из четырех сторон.
InsetDrawable insetDrawable = new InsetDrawable(drawable, insetLeft, insetTop, insetRight, insetBottom);
он специально используется для установки фона drawable, размером меньше или чем вид.
См. Здесь : https://developer.android.com/reference/android/graphics/drawable/InsetDrawable.html
старый вопрос, но ни один из ответов работал для меня. Однако этот 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>
если растровое изображение шире, чем в высоту, используйте
android:gravity="fill_vertical"
. В противном случае, используйтеandroid:gravity="fill_horizontal"
. Это имеет тот же эффект, что и использование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
папка и другая в .
чтобы поместить изображение в доступное пространство (или если вы установили ширину и высоту в dp), я попробовал этот подход, если изображение не слишком широкое.
здесь я установил одинаковую ширину и высоту для квадратных изображений [или вы можете wrap_content на обоих].
<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>
настроить вид границы и масштабы центр тип подходит делать трюк.