将背景图片设置为视图时,我的视图会被拉伸。

32

我为一个视图创建了一个背景图位图,现在这个视图被拉伸到与背景图一样的大小....

这种情况正常吗?

<?xml version="1.0" encoding="utf-8"?>
    <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
        android:src="@drawable/green"
        android:tileMode="repeat"/>
这是我如何将它应用于我的视图。
v.setBackgroundResource(R.drawable.backgroundgreen);
例如,如果图像的高度为500px,视图的高度为200px(设置为wrap_content作为高度),在将图像设置为背景后,我的视图高度变为500px...

你能发布你的图片吗? - vanleeuwenbram
8个回答

36

我也遇到了同样的问题。

如果背景图片的尺寸大于视图的尺寸,则视图的尺寸会改变以匹配图片的尺寸。

解决方案


  1. 将视图放置在相对布局中。
  2. 移除背景图片。
  3. 在相对布局中的视图之前添加一个ImageView。
  4. 将ImageView的src设置为您的背景图片。

    <RelativeLayout
        .
        .
        . >
    
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/yourViewId"
            android:layout_alignRight="@+id/yourViewId"
            android:layout_alignTop="@+id/yourViewId"
            android:layout_alignBottom="@+id/yourViewId"
            android:adjustViewBounds="true" 
            //this will allow the image to resize with same proportions
            android:src="@drawable/yourDrawable" />
    
        <YourView
            android:id="@+id/yourViewId"
            .
            ..
            ... />
    
      </RelativeLayout>
    
    这当然可以在代码中完成。

2
我无法让它正常工作...仍然显示完整的图像...使用您完全相同的代码:s 我错过了什么吗? - Mars
你是否在RelativeLayoutYourView两个控件中都使用了wrap_content - Sherif elKhatib
在RelativeLayout中:android:layout_width="fill_parent"为什么? - Sherif elKhatib
哎呀,你说得对。但是即使去掉那个也没有解决问题……你确定这对你起作用吗?而且这样背景甚至都没有平铺:s - Mars
1
作为我的代码示例,我有一个额外的评论:根据您的视图和背景图像的纵横比以及所需的目标设计,您可能最终需要向ImageView添加android:scaleType="fitXY",以确保完全覆盖您的背景。 - Nantoka
显示剩余5条评论

29
根据我的理解,您所面临的问题并不是问题,而是Android用于设计布局的方式。
这意味着您可以使用3个默认常量值设置高度和宽度:
FILL_PARENT 视图请求的高度或宽度的特殊值。 FILL_PARENT 表示视图希望尽可能大,减去父元素的填充(如果有)。此值在 API 级别 8 中已弃用,并由 MATCH_PARENT 替换。
MATCH_PARENT 视图请求的高度或宽度的特殊值。 MATCH_PARENT 表示视图希望尽可能大,减去父元素的填充(如果有)。引入于 API 级别 8。
WRAP_CONTENT 视图请求的高度或宽度的特殊值。 WRAP_CONTENT 表示视图希望足够大,以适合其自身的内部内容,考虑到其自身的填充。
当您将视图的高度/宽度设置为 WRAP_CONTENT 时,您允许视图占用足够的大小以显示视图的内容。背景图像也是视图的内容,因此您的视图将显示与图像一样大小。这不是问题,这就是它的显示方式。
好吧,但在您的情况下,这对您来说是一个问题,因为您需要显示背景,而视图不应该因此而拉伸。我可以提供几种方法:
  1. 首先,制作正确大小的图片并将其保存在不同的drawable文件夹中。

  2. 指定视图的大小不要使用常量,而是使用DP。如果需要,为不同的尺寸制作不同的布局XML文件并将它们保存在布局文件夹中。

  3. 您可以使用非常有用的设计布局工具layout weight


3
弗兰肯斯坦,你是对的。然而在安卓系统中,似乎无论layout_width和layout_height如何,背景图都会决定视图的大小:(!你的解决方案是正确的,但我认为他们应该允许相反的逻辑:视图决定背景图的大小。再次感谢! - Sherif elKhatib
1
最后一个链接(布局权重)已经失效。您能否在答案中解释一下布局权重技术是什么? - Piovezan
1
根据这篇文章http://developer.android.com/training/improving-layouts/optimizing-layout.html,使用layout_weight可能会非常昂贵,因为每个子项需要测量两次。因此,我认为与MKJParekh的想法相反,如果可以使用其他技术,不建议使用layout_weight。 - Jorge Casariego
我也这样认为,所以我已经将它放在第三优先级了。无论如何,你是完全正确的。@JorgeCasariego - MKJParekh

3

我建议创建一个包装布局,并将背景图像放在其中。我就是这样使用的,非常适合。 请看下面的示例:

<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/settingstab_scroll"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="vertical"
    android:background="@drawable/wareninja_wallpaper_img"
    >
<!-- your layouts and components goes here -->
</ScrollView>


...
AspiroTV的社交编程平台


2
原因很简单。你需要查看View::getSuggestedMinimumWidth/Height方法。
protected int getSuggestedMinimumWidth() {
    return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}

protected int getSuggestedMinimumHeight() {
    return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
}

看到这一点,你可能会知道为什么背景会使视图更大,特别是为什么要将BitmapDrawable分配给它。
简单的解决方案是包装该Drawable(例如BitmapDrawable),然后为getMinimumHeight()和getMinimumWidth()返回0,并最好重写getIntrinsicHeight()和getIntrinsicWidth()以返回-1。
support-v7有一个DrawableWrapper,当需要时委托调用另一个drawable。您可以扩展该类并覆盖上面提到的方法。
如果您不使用support-v7(哇!你太棒了),将该类复制到您的项目中也可以。

https://android.googlesource.com/platform/frameworks/support/+/1949ae9aeaadf52ad7bd7bb74ca5419c67ea7f65/v7/appcompat/src/android/support/v7/internal/widget/DrawableWrapper.java


不错的简单解决方案! - W.K.S

1

对我来说它是有效的。

< ?xml version="1.0" encoding="utf-8"?>
 < LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="@+id/LinearLayoutTest">    

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.prueba);


    ((LinearLayout)findViewById(R.id.LinearLayoutTest)).setBackgroundResource(R.drawable.greenrepeat);
}

在你的代码中,v是什么?它有填充父级的参数吗?

v是列表视图中的自定义列表项,其根视图是线性布局...在您的测试中,视图比背景大还是小?因为我的背景比视图大。 - Mars

0

不要使用android:tileMode="repeat"。你的绿色可绘制对象比视图大还是小?可以添加更多细节吗?


我的背景比视图大,但如果稍后添加更多内容,则视图可能会被拉伸... - Mars

0

在我的情况下,一个完美的解决方案是扩展View并覆盖onMeasure()方法。

以下是步骤:

  1. 创建自己的类并扩展您想要使用的View,例如我将使用Button
  2. 覆盖onMeasure()方法并在底部插入代码。这将在第一次测量完成后设置背景资源。对于第二次测量事件,它将使用已经测量的参数。

以下是扩展Button的自定义视图的示例代码(将Button更改为您想要扩展的View)

public class MyButton extends Button {

    boolean backGroundSet = false;

    public MyButton(Context context) {
        super(context);
    }

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);          
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        if(backGroundSet) {
            setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight());
            return;
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        backGroundSet = true;
        setBackgroundResource(R.drawable.button_back_selector);

    }
}

这里唯一需要更改的是您想要扩展的视图类型,以及在 onMeasure() 方法中您想要为该视图使用的背景资源。
之后,只需在您的布局 xml 中使用此视图或按程序添加即可。

0

我修改了Sherif elKhatib的代码,现在它对我有效:

  1. 如果我们想要将背景图片拉伸成视图图片:

         <RelativeLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content">
    
             <ImageView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_alignStart="@+id/yourViewId"
                 android:layout_alignTop="@+id/yourViewId"
                 android:layout_alignEnd="@+id/yourViewId"
                 android:layout_alignBottom="@+id/yourViewId"
                 android:scaleType="fitXY"
                 android:src="@drawable/bg_very_big_picture" />
    
             <LinearLayout
                 android:id="@+id/yourViewId"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
    
  2. 如果我们不想将背景图片拉伸,而是将其裁剪以适应视图图片:

         <RelativeLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content">
    
             <ImageView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_alignStart="@+id/yourViewId"
                 android:layout_alignTop="@+id/yourViewId"
                 android:layout_alignEnd="@+id/yourViewId"
                 android:layout_alignBottom="@+id/yourViewId"
                 android:scaleType="centerCrop"
                 android:src="@drawable/bg_very_big_picture" />
    
             <LinearLayout
                 android:id="@+id/yourViewId"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接