为什么 android 无法解析符号但它仍然有效?

Why android cannot resolve symbol but it still works?

我有一个 FrameLayout,它在点击时会产生连锁反应。为此,我在我的 FrameLayout 上有这个标签:

android:foreground="?attr/selectableItemBackgroundBorderless"

问题是我收到一条错误消息:"Cannot resolve symbol '?attr/selectableItemBackgroundBorderless'"。尽管有错误,我仍然可以 运行 项目和 FrameLayout 有我想要的效果。

但如果我尝试改用此标签:

android:foreground="?android:attr/selectableItemBackgroundBorderless"

我收到另一个错误。它说这个标签需要 API 级别 21.

所以我的问题是,这样做的正确方法是什么?我应该继续使用无法解析符号并忽略错误的那个吗?有没有其他方法可以让另一个标签有类似的行为?

?android:attr/selectableItemBackgroundBorderless for a ripple that extends beyond the view. It will be drawn upon, and bounded by, the nearest parent of the view with a non-null background.

  • selectableItemBackgroundBorderless 是引入的新属性 API 21 级.

如果你想使用这个,然后打开你的 MODULE LEVEL build.gradle 并设置

    compileSdkVersion 27
    buildToolsVersion "27.0.3"
    defaultConfig {
        applicationId "\"
        minSdkVersion 21
        targetSdkVersion 27

确保在 PROJECT LEVEL build.gradle 部分添加 google()

repositories {
        ....
        google() //maven { url 'https://maven.google.com' }
    }

结构

<!-- Background drawable for borderless standalone items that need focus/pressed states. -->
 <attr name="selectableItemBackgroundBorderless" format="reference" />

注意

If your code is deliberately accessing newer APIs, and you have ensured (e.g. with conditional execution) that this code will only ever be called on a supported platform, then you can annotate your class or method with the @TargetApi annotation specifying the local minimum SDK to apply, such as @TargetApi(11), such that this check considers 11 rather than your manifest file's minimum SDK as the required API level.

XML为此,

android:foreground="?android:attr/selectableItemBackgroundBorderless"
tools:targetApi="lollipop"

欲了解更多信息,

  • Android Cannot resolve symbol '?attr/selectableItemBackground'

source code of support library appcompat-v7可以看出?attr/selectableItemBackgroundBorderless?android:attr/selectableItemBackgroundBorderless的别名:

<item name="selectableItemBackgroundBorderless">?android:attr/selectableItemBackgroundBorderless</item>

而从Android platform source code可以看出selectableItemBackgroundBorderless是平台21版本新增的资源:

<public type="attr" name="selectableItemBackgroundBorderless" id="0x0101045c" />

当您使用以下内容时:

android:foreground="?attr/selectableItemBackgroundBorderless"

您正在使用支持库提供的资源。在我看来,这个错误是因为 Android Studio 试图知道在 api below 21 中找不到的原始资源。因为找不到原始资源,它将回退到提供的资源由支持库提供。

不要直接分配 android:foreground,而是让 FrameLayout 使用样式:

<FrameLayout 
    style="@style/MyStyle"
    ....>

res/values/styles.xml 上,添加以下内容:

<style name="MyStyle">
    <item name="android:foreground">?attr/selectableItemBackgroundBorderless</item>
</style>

然后在 res/values-v21/styles.xml 上添加带有 android: 前缀的符号:

<style name="MyStyle">
    <item name="android:foreground">?android:attr/selectableItemBackgroundBorderless</item>
</style>

android:foreground="?android:attr/selectableItemBackgroundBorderless" 只能在 api 21 或更高版本上使用。如果你想要 app-compat 版本,你应该删除 android 部分。 (也可以去掉attr部分,等于不去掉)。

以下两种方法都适用于 api 小于 21 并且完全相同:

android:foreground="?attr/selectableItemBackgroundBorderless"

android:foreground="?selectableItemBackgroundBorderless"

对我有帮助:

  1. 在 Android Studio 中打开您的项目。
  2. 构建 -> 清理项目。
  3. 打开项目目录。
  4. 删除以下目录:.idea、.gradle
  5. 返回 Android 工作室。
  6. 文件 -> 使缓存无效/重新启动... -> 无效并重新启动。
  7. 文件 -> 与 Gradle 文件同步项目

希望对您有所帮助。

设置为android:background="?android:attr/selectableItemBackground"