为什么`android:foreground`属性不起作用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么`android:foreground`属性不起作用?相关的知识,希望对你有一定的参考价值。

看看这个小的android应用程序:

main activity.Java:

package io.github.gsaga.toucheventtest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

activity_main:

<ImageView android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="@drawable/ic_launcher_background"
    xmlns:android="http://schemas.android.com/apk/res/android" />

android:foreground指向的图像没有显示,但是如果我在foreground中将src更改为backgroundactivity_main.xml则会出现。此代码似乎遵循此处描述的说明:

https://developer.android.com/reference/android/view/View.html#attr_android:foreground

为什么android:foreground标签不适用于上面的代码?

注意:

minSdkVersion19,我在Android 5.1API level 22)运行这个应用程序

答案

Short answer

这是由于API级别23以来Android中存在的错误。

More details on the behavior

以下是所有XML属性的列表以及与通过FrameLayout引入的API级别将前景drawable设置为视图相关的相应方法。但是,这些后来被转移到API级别23的View

╔════════════════════════════╦═════════════════════════════════════════════════╦═════════════╗
║       XML attribute        ║                     Method                      ║   Added in  ║
║                            ║                                                 ║ (API level) ║
╠════════════════════════════╬═════════════════════════════════════════════════╬═════════════╣
║ android:foreground         ║ setForeground(Drawable)                         ║ 1           ║
╠════════════════════════════╬═════════════════════════════════════════════════╬═════════════╣
║ android:foregroundGravity  ║ setForegroundGravity(int gravity)               ║ 1           ║
╠════════════════════════════╬═════════════════════════════════════════════════╬═════════════╣
║ android:foregroundTint     ║ setForegroundTintMode(PorterDuff.Mode tintMode) ║ 21          ║
╠════════════════════════════╬═════════════════════════════════════════════════╬═════════════╣
║ android:foregroundTintMode ║ setForegroundTintMode(PorterDuff.Mode tintMode) ║ 21          ║
╚════════════════════════════╩═════════════════════════════════════════════════╩═════════════╝
  • Android doc说,setForeground(Drawable)在API 1中添加,setForegroundTintList (ColorStateList tint)setForegroundTintMode (PorterDuff.Mode tintMode)在API级别21中添加到View。这是错误的。在FrameLayout有直到API 23。
  • 在API级别<23,即使不需要,您也会收到警告。你可以压制它。见this

现在来看看这些属性如何在不同版本上运行。

╔═══════════╦══════════════════╦══════════════════╗
║ API level ║      By code     ║     Using XML    ║
╠═══════════╬══════════════════╬══════════════════╣
║ <23       ║ FrameLayout only ║ FrameLayout only ║
╠═══════════╬══════════════════╬══════════════════╣
║ >=23      ║ FrameLayout only ║ All views        ║
╚═══════════╩══════════════════╩══════════════════╝

The cause of the bug

当这些属性在API级别23中移动到View时,他们对它进行了一些奇怪的修改,可以称之为bug。在从XML加载属性时,它检查View是否是FrameLayout,它不存在于我们可以用于相同目的的方法中。

查看构造函数,API级别23:

case R.styleable.View_foreground:
    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
        setForeground(a.getDrawable(attr));
    }
    break;
另一答案

要在android:foregroundAndroid 5.1上使用API level 22,你没有正确使用android:foreground

因为它的名字清楚地表明你可以在任何内容(如叠加)的顶部/前景上设置drawable,即你可以在FrameLayout中放置一些视图,你可以使用android:foreground。在这个FrameLayout内添加你的ImageView

Documentation

定义drawable以绘制内容。这可以用作叠加层。如果重力设置为填充,则前景drawable参与内容的填充。

以下是用法示例:

<FrameLayout
    android:id="@+id/share"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:foreground="@drawable/ic_launcher_background>

    // your ImageView here
    <ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</FrameLayout>

注意:对于API level > 23,它将在没有FrameLayout的情况下工作。

我希望这能帮到您。

另一答案

看起来像是一次(API <23),android:foreground只会与FrameLayout合作,正如VicJordan所暗示的那样。但是,对于API 23+,android:foreground似乎适用于任何视图类型。请参阅View.java源中的this选择:

case R.styleable.View_foreground:
    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
        setForeground(a.getDrawable(attr));
}

以下是使用以下布局在qamxswpoi上工作的示例:

android:foreground

<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:foreground="@drawable/ic_launcher_foreground" android:src="@android:drawable/ic_delete" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>

然而,在API 22上,我们看到:

enter image description here

没有前景图片。因此,enter image description here仅在API级别为23+时才有效。我同意这并没有真正记录,但这就是它的方式。

更新:API 23似乎与android:foreground有问题,所以让我们说android:foreground适用于API 24+以获取一般视图。

第二次更新:遇到了几个关于android:foreground setForeground()here的同样问题的其他帖子。在第二个问题的接受答案中,CommonsWare将其识别为“文档错误”。

以上是关于为什么`android:foreground`属性不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

Android FrameLayout的android foreground属性可以设置单击时的前景色

Android ImageView属性

权限拒绝:startForeground 需要 android.permission.FOREGROUND_SERVICE

FrameLayout 中的 'android:foreground' 和 'android:foregroundGravity' 如何影响其外观?

媒体投影需要 Android Pie 和 Q 中类型为 ServiceInfo.FOREGROUND_SERVICE TYPE_MEDIA_PROJECTION 的前台服务

复制资源/android/icon/mdpi-foreground.png 时出错