平铺可绘制对象有时会被拉伸。

55

我有一个ListView,其中每个条目都有瓷砖背景。为了实现这一点,我使用以下drawable xml:

<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/tile"
    android:tileMode="repeat" />

通常情况下,这个方法是有效的。然而有时候,src drawable并没有被平铺,而是被拉伸以填充整个列表项。(我有几个不同的这样的图块,并且我在一个ListView中混合使用它们。如果出现拉伸而不是平铺,那么它从来没有同时出现在所有图块中,就这点而言也许有些帮助。)

我还尝试在xml中添加android:dither="true",因为我在某个地方读到说如果没有它可能会出现错误。但这并没有改变任何东西。

有人遇到过同样的问题吗?你是如何解决的?


2
我也遇到了同样的问题。已经有解决方案了吗? - danh32
1
我也可以确认这种行为。在我的情况下,它似乎是完全随机的。平铺背景可绘制对象有时不会被平铺。而是被拉伸到整个区域或者只是水平平铺垂直。我还没有找到解决方案。但我把它放在这里,所以如果有人有确切的问题可以联系 :) - Janar Jürisson
1
这里也有同样的问题。Zulaxia提供的通过编程重新应用tilemode的解决方案有时确实可以修复它,但通常仍然会被设置回拉伸模式。对我来说,它只发生在我在选择器状态列表中使用的平铺可绘制层列表中,并将其作为按钮背景应用的情况下。Greg的评论,即问题可能与在回收视图中重置tilemode有关,与我在这里看到的情况非常吻合。 - user934328
1
已确认在这里也发生了。它发生在我的适配器中的public View getView(int position, View convertView, ViewGroup parent)方法中。 - Richard Lalancette
2
刚刚收到一封来自Android漏洞跟踪器的电子邮件,说这个问题在ICS中已经解决了。 - Zulaxia
显示剩余2条评论
8个回答

39
我也遇到了这个问题。很难诊断,更难找到类似的报告和可用的解决方案。
在freenode #android-dev irc频道上,“Tapas”提供了以下实用方法:
public static void fixBackgroundRepeat(View view) {
    Drawable bg = view.getBackground();
    if (bg != null) {
        if (bg instanceof BitmapDrawable) {
            BitmapDrawable bmp = (BitmapDrawable) bg;
            bmp.mutate(); // make sure that we aren't sharing state anymore
            bmp.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
        }
    }
}

将其应用于所有设置了平铺背景的视图(例如,findViewById它们)。

另外,我有印象这个bug在AndroidManifest.xml中设置"anyDensity=true"后开始出现问题。


谢谢,这很有帮助,至少暂时是这样。 - jki
2
我该如何将它应用到在xml中定义的drawable上?我在<selector>中使用这个drawable。 - Kirill Kulakov
1
这个解决方案对我也有效,但是视图背景没有被奇怪地设置,所以我不得不在view.getBackground()之前添加view.setBackgroundResource(R.drawable.bg_striped_img);。谢谢 :) - letroll

9
我刚遇到了和 CLAMP TileMode 相同的问题。我有一个位图,想将其在底部拉伸,已将其设置为 XML 定义的 BitmapDrawable,在 Graphical Preview 窗口中一切看起来都很好,无论我将 ViewImage 的大小设置为多少,它都会在顶部绘制我的位图,然后重复最后的像素以填充到结束。
在模拟器上启动应用程序的各种 SDK 构建版本以及在我的手机上都产生了直接“填充”类型的扭曲,这完全没用。
解决方案就是每次在我的代码中更改 ImageView 的大小时重新应用 TileMode:
((BitmapDrawable)ascender.getDrawable()).setTileModeY(TileMode.CLAMP);

现在一切都很顺利。所以,对我来说这看起来像是一个错误。

6
这个话题在网络上引起了很多争议,有很多各种各样(也很多)的解决方法。如果您仍然不知所措,我的建议是将所有平铺位图资源保持为正方形,��于2的维度。 即: 对于xhdpi平铺资源,其尺寸应为16px x 16px。
我希望安卓平台能够“过度平铺”,以填充未完全镶嵌的位图,并修剪浪费部分。但是,跨越mdpi、hdpi和xhdpi(以及v2.3到v4.0)进行10px * 10px平铺位图的实验表明,这种拉伸是“不一致”的。
基于2的维度允许在通过各种分辨率并且每次视图创建时,每个设备试图绘制瓷砖的过程中进行整体和均匀划分。
在Android开发中,我们面对着不同硬件以及厂商介入平台 - 有时这种琐碎的黑科技只是有效的。
至少对我来说,这似乎已经解决了问题。值得一试。

谢谢。那救了我一命。但问题似乎只存在于某些特定设备上。当在模拟器上运行相同的Android版本和屏幕分辨率时,可以针对我测试过的任何大小重复背景。 - MTilsted

6

2

这听起来像是一个 bug,虽然我自己从未遇到过。如果您有一个能够重现此问题的简单 APK,请将其发送给我(romainguy /at/ android.com),或在此处报告错误。


1
每次我在一个选择器状态内创建平铺位图时,都会遇到这个问题。这是通过xml工作的,并将选择器放置在Button或ImageButton上。 - Jona

1

这篇博客讨论了这个问题。

结合Ivo van der Wijk列出的这个解决方案,对我很有效。

关键是要从XML中删除平铺设置,然后在运行时将其设置为平铺。如果两者都设置为平铺,则对我无效。

编辑:实际上,我撒谎了。即使这样做,有时似乎仍然无法平铺。

非常希望有一个可靠的解决方法。

编辑2:将其设置为其他值(例如CLAMPED),然后再将其设置回来似乎是有效的。


1
我也遇到了同样的问题。我所缺少的是,在xml位图正常工作时,我们需要在imageview中添加scaletype以适应XY。

tile_bitmap.xml

<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/tile"
    android:tileMode="repeat" />

layout.xml

<ImageView
    android:layout_width="match_parent"
    android:src="@drawable/tile_bitmap"
    android:layout_height="match_parent"
    android:scaleType="fitXY"/>

0

我将我的图片从drawable-xhdpi文件夹移动到drawable文件夹,一切都很好。


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