可能出现超绘:根元素绘制背景

40

在运行Android Lint时,我遇到了这个警告:

可能会出现过度绘制:根元素使用了带有背景的主题@drawable/main,并且该主题也绘制了一个背景。

推断的主题是@android:style/Theme.NoTitleBar.Fullscreen

有人可以解释一下为什么会出现这个警告,以及如何去除它吗?

我的XML代码:

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@drawable/main" //***LINT warning***
        android:orientation="vertical"
        android:weightSum="3" >

主题定义在清单中的部分

 <application
        android:icon="@drawable/ic_logo"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
6个回答

31
为了优化应用程序的性能(避免过度绘制),您可以执行以下操作:
  • res/values/styles.xml中声明主题

<style name="MyTheme" parent="android:Theme">
    <item name="android:background">@drawable/main</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowFullscreen">true</item>
</style>
  • 更改清单文件:

  • 修改 Manifest 文件:

  • <application
        android:icon="@drawable/ic_logo"
        android:label="@string/app_name"
        android:theme="@style/MyTheme" >
    
  • 删除"My xml"中的background声明

  • 17
    如果我需要为应用程序的某些部分设置不同的背景,该怎么办? - Franco
    10
    只需为您的视图创建一个带有背景项的单独样式。我知道这只是一种解决方法,因此您可以将tools:ignore设置为“Overdraw”。 - Ov3r1oad
    @Franco,您可以将它们放在不同的活动中,每个活动都有不同的主题。 - Marcin Koziński
    5
    如果您只想更改内容的背景(不包括工具栏等),请使用windowBackground,如下所示: <item name="android:windowBackground">@drawable/main</item> - shyamal
    杰出的解决方案 - Mohammad Elsayed

    19

    更新

    请查看评论或者点击此链接。正如Marcin所提到的,我的解决方案并不是一个好方法,因为它可能会导致伪像。我一直在使用它来避免过度绘制,没有任何问题,但总的来说,根据Chet Haase对这种技术的评论,它可能不是一个通用的规则。

    原始回答

    我发现最好的方法是将默认背景设置为null,并在每个布局中应用所需的背景。

    原因是当你在主题中设置默认背景,甚至是不同的主题带有不同的背景,这意味着整个布局都将填充该背景。在大多数情况下,您不需要100%填充屏幕的背景,因为您在该背景上面有工具栏,标题,页脚和其他元素,这些元素会导致过度绘制。

    要在主题中应用空背景:

    <style
        name="ThemeName" parent="ParentTheme">
        <item name="android:windowBackground">@null</item>
    </style>
    

    要检查过度绘制,只需在模拟器/设备的开发选项中激活“显示过度绘制”选项。不要完全相信lint警告,因为跟踪器中存在一些错误,我不确定是否完全修复。

    更多信息,请参见: 什么是过度绘制,为什么会成为问题?


    1
    你提出的推理很有道理,但请查看为Android开发VIII制定规则:用户界面中“避免空窗口背景”部分,了解这种方法可能存在的缺点。 - Marcin Koziński
    @Marcin,尽管Chet建议使用默认背景,但很难避免在工具栏和其他布局元素上进行过度绘制,因为背景将始终匹配整个屏幕大小。 - Sotti

    2
    你收到这个lint警告的原因是你的activity和线性布局都尝试绘制背景。因此,可见区域被绘制了两次。
    如何调试呢?运行sdk/tools/hierarchyviewer并检查视图层次结构,查看哪个视图有未显示的背景。(你需要在运行dev build rom的android设备上进行)
    底层运行什么?请注意,几乎所有android主题都指定了背景,这意味着如果你想创建一个覆盖整个屏幕并具有背景的“LinearLayout”,最好将activity的windowBackground设置为“@null”或者在线性布局中删除背景设置。

    0

    更加暴力的方法。在你的自定义 theme.xml 中实现。

    <style name="MyTheme" parent="Theme.MaterialComponents.Light.Bridge">
         ...
        <item name="android:windowBackground">@color/white</item>
         ...
    </style>
    

    0
    如果您在 FragmentManager 中有相互替换的代码片段,则可以删除背景的附加绘制。因此,如果您有...
    val fragment = YourFragment.newInstance()
    parentFragmentManager.beginTransaction().run {
        replace(R.id.container, fragment, YourFragment.TAG)
        addToBackStack(YourFragment.TAG)
    }.commitAllowingStateLoss()
    

    然后该片段将替换当前的片段,并具有活动的背景。在这种情况下,您可以省略片段中的android:background="@color/..."

    但是,如果删除android:background添加一个片段到当前的片段上使用add,它将具有透明的背景,以便视图会重叠在一起。您将看到两个片段一个在另一个上面。

    为了检查这种行为,您可以暂时在styles.xml中的AppTheme中添加<item name="android:windowBackground">@color/...</item>,如前所述。


    0
    如果某些屏幕的背景与常规的AppTheme背景不同,那么请扩展AppTheme并在新主题中更改背景。
       <style name="AppThemeWithWhiteBackground" parent="AppTheme">
            <item name="android:background">@color/white</item>
        </style>
    

    将该样式应用于根布局。
    style="@style/AppThemeWithWhiteBackground"
    

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