【问题标题】:Shading artifact beneath an ImageView with a png that have fully transparent background具有完全透明背景的 png 的 ImageView 下的着色工件
【发布时间】:2026-02-23 17:00:01
【问题描述】:

我正在开发 Gingerbread (2.3.3) 设备。我有一个 ImageView,其中包含一个箭头图,并且有一个完全透明的背景,我需要在某些背景上绘制。问题是 ImageView 的边界框下方有一个“阴影”伪影。
如果你仔细观察下图,你会看到我所说的神器:1

前景图像和背景图像都有 alpha 通道,因此被解码为 ARGB8888(我通过手动将它们的资源解码为位图来仔细检查,打印出显示 ARGB8888 的位图配置,然后将它们分配给它们各自的意见)。在调用 setContentView() 之前,我还将 Activitiy 的窗口配置为 PixelFormat.RGBA_8888。

请不要向我推荐建议将位图解码为 ARGB8888 和/或将窗口设置为 RGBA_8888 的线程,因为我尝试了两种解决方案,但都没有帮助。

有什么想法可以解决这个问题吗?

编辑:

这是设置窗口像素格式和可绘制对象的函数(直接从 onCreate() 调用):

public void testTransparency() {
    getWindow().setFormat(PixelFormat.RGBA_8888);
    setContentView(R.layout.transparency_test);
    LinearLayout ll = (LinearLayout)findViewById(R.id.ll);      
    Bitmap bgBmp = BitmapFactory.decodeResource(getResources(), R.raw.bg);
    Log.d(TAG,"BG BMP Config: " + bgBmp.getConfig());
    ll.setBackgroundDrawable(new BitmapDrawable(bgBmp));
    ImageView iv = (ImageView)findViewById(R.id.iv);
    iv.setBackgroundDrawable(null);
    Bitmap arrowBmp = BitmapFactory.decodeResource(getResources(), R.raw.big_arrow);
    Log.d(TAG,"Arrow BMP Config: " + arrowBmp.getConfig());
    iv.setImageBitmap(arrowBmp);
}

这是我的测试使用的(非常简单的)布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:id="@+id/ll"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="vertical"  
    android:gravity="center">

<ImageView android:id="@+id/iv"
    android:layout_width="72dp"
    android:layout_height="120dp"
    /></LinearLayout>

“bg”资源可以在2找到
'big_arrow' 资源可以在“http://i.imgur.com/3V6QU.png”找到

编辑 2:
我发现我无法在模拟器上重现该问题,也无法在我的 N1 (2.3.4) 或 XOOM (3.2.1) 上重现该问题。从这里继续有 2 个选项:
1. 问题是特定于设备的(我正在开发基于 Android 的设备)
2. 2.3.4 和 32BPP 帧缓冲区在渲染透明 PNG 时存在特定问题。

谢谢。

【问题讨论】:

  • 你能发布你解码成的 ImageView 的 xml 吗?我以前从未在我的任何图形上看到过这种效果,所以不知道是什么原因造成的。
  • @Kaediil 我在原帖中添加了代码 sn-ps
  • 有趣,我在你的截图中看到了,但在我运行代码时没有在我的模拟器中看到。
  • 您是如何生成在 ImageView 上显示较暗框的屏幕截图?
  • @Kaediil 我使用 DDMS 捕获了屏幕截图

标签: android transparency png-transparency


【解决方案1】:

发现了这个错误,确实是一个特定于平台的错误。

我发现当我在 SKIA 的混合 blitting 部分(在 SkBlitRow_D32.cpp - SkBlitRow::Proc32 SkBlitRow::Factory32(unsigned flags) 中)移除霓虹灯优化时,着色伪影消失了.

对于任何想要调试此类错误的人来说,这是一个有用的提示:
您始终可以将视图层次结构绘制为位图(例如,参见:Android get a bitmap of a view before drawing?),然后使用 Bitmap.compress 方法将位图导出为 PNG 文件。通过这种方式,您可以获得带有 alpha 通道的视图层次结构快照(它不会出现在 DDMS 屏幕截图中,因为它是在合成后生成的)。我通过这种方式发现阴影区域内的 alpha 值是“1”而不是“0”,从而创建了工件。

【讨论】:

    【解决方案2】:

    简单设置

    BackButton.setBackgroundColor(Color.TRANSPARENT);
    

    解决了我在 Android 2.3.5 的 HTC Desire HD 上的 ImageButton 问题,我的按钮图像的高度低于默认背景。经验观察;工件未在搭载 Android 4.1.2 的 Galaxy Note 1 上显示

    【讨论】: