为什么`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
更改为background
或activity_main.xml
则会出现。此代码似乎遵循此处描述的说明:
https://developer.android.com/reference/android/view/View.html#attr_android:foreground
为什么android:foreground
标签不适用于上面的代码?
注意:
minSdkVersion
是19
,我在Android 5.1
(API 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:foreground
即Android 5.1
上使用API level 22
,你没有正确使用android:foreground
。
因为它的名字清楚地表明你可以在任何内容(如叠加)的顶部/前景上设置drawable,即你可以在FrameLayout
中放置一些视图,你可以使用android:foreground
。在这个FrameLayout内添加你的ImageView
。
定义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上,我们看到:
没有前景图片。因此,仅在API级别为23+时才有效。我同意这并没有真正记录,但这就是它的方式。
更新:API 23似乎与android:foreground
有问题,所以让我们说android:foreground
适用于API 24+以获取一般视图。
第二次更新:遇到了几个关于android:foreground
setForeground()
和here的同样问题的其他帖子。在第二个问题的接受答案中,CommonsWare将其识别为“文档错误”。
以上是关于为什么`android:foreground`属性不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
Android FrameLayout的android foreground属性可以设置单击时的前景色
权限拒绝:startForeground 需要 android.permission.FOREGROUND_SERVICE
FrameLayout 中的 'android:foreground' 和 'android:foregroundGravity' 如何影响其外观?
媒体投影需要 Android Pie 和 Q 中类型为 ServiceInfo.FOREGROUND_SERVICE TYPE_MEDIA_PROJECTION 的前台服务