69

如何使背景图像适合视图但在<bitmap />用作背景可绘制 XML 时保持其纵横比?<bitmap>的值都没有android:gravity给出预期的效果。

4

9 回答 9

65

仅在 xml 文件中实现操作背景属性是不可能的。有两种选择:

  1. 您以编程方式剪切/缩放位图 Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)并将其设置为 someView的背景。

  2. 您使用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>
    
于 2012-03-27T14:49:24.260 回答
36

有一种简单的方法可以从可绘制对象中做到这一点:

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>

唯一的缺点是,如果没有足够的空间,您的图像将不会完全显示,但会被剪裁,我找不到直接从可绘制对象中执行此操作的方法。但从我所做的测试来看,它工作得很好,而且它并没有剪掉那么多的图像。您可以更多地使用重力选项。

另一种方法是只创建一个布局,您将在其中使用 anImageView并将其设置scaleTypefitCenter.

希望这些信息可以帮助您实现您想要的。

于 2014-02-21T09:05:47.260 回答
5

我想在我的自定义 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);
            }
        }
    }
}

使用这种方法,您可以灵活地应用您需要的任何缩放逻辑

于 2017-06-23T12:48:45.890 回答
3

另一种方法是为您的常规图像创建补丁 9 图像,并让它按照您想要的方式进行缩放。

您可以通过在角落放置 9 个补丁点来使其内容居中,这将明显保持您的比例(假设图像的最外边缘是可重复的/透明的)。

希望你明白这一点。

于 2012-09-12T20:49:52.017 回答
3

如果您的位图宽于高,请使用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文件夹中创建另一个drawable-land

于 2017-05-04T23:00:56.237 回答
2

使用 a.ch 描述的方法对我来说效果很好,除了我使用了这种比例类型,它对我需要的效果更好:

android:scaleType="centerCrop"

以下是可用比例类型的完整列表:http: //developer.android.com/reference/android/widget/ImageView.ScaleType.html

于 2013-08-12T17:02:30.167 回答
2

尝试使用 InsetDrawable (对我来说效果很好)。

只需从四个侧面中的任何一个给它您想要的可绘制对象和插图(或填充)。

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

它专门用于设置背景可绘制,尺寸小于或小于视图。

见这里: https ://developer.android.com/reference/android/graphics/drawable/InsetDrawable.html

于 2017-01-13T08:51:29.530 回答
2

老问题,但没有其他答案对我有用。但是,此 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>
于 2017-02-07T15:24:41.780 回答
0

为了使图像适合可用空间(或者如果您在 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>

adjust view boundsscale type center fit成功了。

于 2018-05-30T04:56:52.357 回答