【问题标题】:Setting a background image to a view stretches my view将背景图像设置为视图会拉伸我的视图
【发布时间】:2012-01-02 09:51:48
【问题描述】:

我为视图创建了背景图像位图,现在视图被拉伸到背景图像的大小......

这正常吗?

<?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);

比如……

如果图像高度为 500 像素 并且视图高度为 200 像素(将 wrap_content 设置为高度) 将图像设置为背景后,我的视图高度变为 500px...

【问题讨论】:

  • 你可以发布你的图片吗?

标签: android view background


【解决方案1】:

我也遇到过同样的问题。

如果背景图像的大小大于视图的大小,则视图的大小将更改以匹配图像的大小。

解决方案


  1. 将视图放在相对布局中。
  2. 移除背景图片。
  3. 在相对布局内的 View 之前添加一个 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>
    

当然,这一切都可以在代码中完成。

【讨论】:

  • 我无法让它工作...仍然显示完整图像...使用您完全相同的代码:我错过了什么吗?
  • 您是否将RelativeLayoutYourView 都包裹了内容?
  • 在RelativeLayout中:android:layout_width="fill_parent"为什么?
  • 因为我希望背景垂直填充屏幕.. 视图的高度对我来说是个问题... :( //edit 刚刚尝试将其设置为包装内容但仍然一样的……
  • 一次附加评论,因为我刚刚将此示例用于我的代码:根据您的视图和背景图像的纵横比以及您所需的目标设计,您最终可能需要添加 android:scaleType="fitXY " 到 ImageView 以确保您的背景被完全覆盖。
【解决方案2】:

在我看来,您面临的问题不是问题,而是使用 Android 设计布局的方式。

这意味着您可以使用 3 个默认常量值设置高度和宽度:

FILL_PARENT
View 请求的高度或宽度的特殊值。 FILL_PARENT 表示视图希望与其父级一样大,减去父级的填充(如果有)。从 API 级别 8 开始不推荐使用此值,并替换为 MATCH_PARENT

MATCH_PARENT
View 请求的高度或宽度的特殊值。 MATCH_PARENT 表示视图希望与其父级一样大,减去父级的填充(如果有)。在 API 级别 8 中引入。

WRAP_CONTENT
View 请求的高度或宽度的特殊值。 WRAP_CONTENT 表示 View 想要足够大以容纳其自己的内部内容,同时考虑到自己的填充。

现在,当您将View 的高度/宽度设置为WRAP_CONTENT 时,您允许视图采用足以显示视图内容的大小。背景图像也是View 的内容,因此您的视图将显示为与图像一样大。这不是问题,就是这样显示的。

好的,但是在您的情况下,这对您来说是个问题,因为您有要显示的背景并且不应该为此拉伸视图。我可以建议几种方法:

  1. 首先并且非常明显:制作正确大小的图像并将它们保存在不同的drawable folders

  2. 不使用constants,而是使用DP 指定视图的大小。如有必要,为不同大小制作不同的布局 XML 文件,并将它们保存在 layout folders 中。

  3. 你可以使用一个非常有用的东西来设计布局是layout weight

【讨论】:

  • 弗兰肯斯坦你是对的。但是在android中,无论layout_width和layout_height如何,背景总是会决定视图的大小:(!您的解决方案是正确的,但我认为他们应该允许相反的逻辑:视图决定了背景的大小. 并再次感谢!
  • 最后一个链接(布局权重)坏了。您能否解释一下答案本身的布局权重技术是什么?
  • @Piovezan 根据这篇文章developer.android.com/training/improving-layouts/… 使用 layout_weight 可能特别昂贵,因为每个孩子需要测量两次。所以,我认为与MKJParekh相反,如果可以使用其他技术,不推荐layout_weight
  • 我也相信这就是为什么我已经把它放在了第三优先级。无论如何,你是绝对正确的。 @JorgeCasariego
【解决方案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>


...
Social Coding @ AspiroTV

【讨论】:

    【解决方案4】:

    它对我有用。

    < ?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 是什么?它有 fill_parent 的参数?

    【讨论】:

    • v 是列表视图中的自定义列表项,其根视图是线性布局...在您的测试中,视图是大于还是小于背景?因为我的背景比视图大..
    【解决方案5】:

    原因很简单。您必须查看 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

    【讨论】:

    • 不错的简单解决方案!
    【解决方案6】:

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

    【讨论】:

    • 我的背景比视图大,但如果稍后添加更多内容,视图可能会被拉伸...
    【解决方案7】:

    在我的情况下完美运行的一个很好的解决方案是扩展 View 并覆盖 onMeasure()

    步骤如下:

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

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

    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 中使用此视图或以编程方式添加它。

    【讨论】:

      【解决方案8】:

      我修改了 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"
        

      【讨论】: