看看这个小型的Android应用程序:
MainActivity.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
)上运行此应用程序
答案 0 :(得分:15)
这是由于自API级别23开始存在于Android中的一个错误。
以下是所有XML属性以及与通过FrameLayout
引入的具有API级别的视图级别的可绘制对象设置视图相关的相应方法的列表。但是,这些后来又移至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文档说,在API 1中添加了setForeground(Drawable)
,在API级别21中将setForegroundTintList (ColorStateList tint)
和setForegroundTintMode (PorterDuff.Mode tintMode)
添加到了View
。这是错误的。直到API 23为止FrameLayout
都存在。
在API级别<23中,即使不是必需的,您也会收到警告。您可以抑制它。参见this。
现在看看这些属性如何在不同版本上工作。
╔═══════════╦══════════════════╦══════════════════╗
║ API level ║ By code ║ Using XML ║
╠═══════════╬══════════════════╬══════════════════╣
║ <23 ║ FrameLayout only ║ FrameLayout only ║
╠═══════════╬══════════════════╬══════════════════╣
║ >=23 ║ FrameLayout only ║ All views ║
╚═══════════╩══════════════════╩══════════════════╝
当这些属性在API级别23中移至View
时,它们对其进行了一些奇怪的修改,这可以称为错误。从XML加载属性时,它会检查View
是否为FrameLayout
,而该case R.styleable.View_foreground:
if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
setForeground(a.getDrawable(attr));
}
break;
在我们可用于同一目的的方法中不存在。
View构造函数,API级别23:
let arr = ["Orebro", "Sundsvall", "Hudriksvall", "Goteborg"];
console.log(arr.sort((a,b)=>b.length-a.length)[0])
答案 1 :(得分:5)
要在android:foreground
上使用Android 5.1
,即API level 22
,则表示您未正确使用android:foreground
。
顾名思义,您可以在诸如叠加层之类的任何内容的顶部/前景上设置可绘制对象,即可以在FrameLayout
中放置一些视图,以便可以使用android:foreground
。在此FrameLayout中添加您的ImageView
。
定义可绘制对象绘制内容。这可以用作 重叠。前景可绘制对象参与填充 重力设置为填充时的内容。
下面是用法示例:
<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
。
我希望这会对您有所帮助。
答案 2 :(得分:1)
就像VicJordan所建议的那样,names
一次只能与android:foreground
一起使用(API <23)。但是,对于API 23+,看来FrameLayout
适用于任何视图类型。请参见 View.java 源中的this选择:
android:foreground
这是case R.styleable.View_foreground:
if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
setForeground(a.getDrawable(attr));
}
在API 28上使用以下布局的示例:
android:foreground
但是,在API 22上,我们看到了以下内容:
无前景图像。因此,<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级别为23+时有效。我同意这并没有真正记录在案,但这只是事实。
更新:API 23似乎与android:foreground
有关,因此,假设android:foreground
在API 24+上可用于一般视图。
第二次更新:还遇到了其他几篇有关android:foreground
here和here的相同问题的文章。在对第二个问题的公认答案中,CommonsWare将其标识为“文档错误”。
答案 3 :(得分:1)
另一种解决方案是用<ripple>
包装图片,将其设置为ImageView
的{{1}},然后将background
和tint
设置为“隐藏” tintMode
图片,以便可以看到上面有波纹的背景图片。
src
<!-- In your layout file -->
<ImageView
android:adjustViewBounds="true"
android:background="@drawable/image_with_ripple"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/image"
android:tint="@android:color/transparent"
android:tintMode="src_in" />
不仅可在API 21+上使用,而且如果您的图像具有圆角-或者是另一种非矩形形状(例如星形或心形图标),则保持其边界,而不是填充视图的矩形边界,这在某些情况下可以提供更好的外观。
有关动画GIF的信息,请参见this Medium article,以了解该技术与使用<!-- drawable/image_with_ripple.xml -->
<?xml version="1.0" encoding="utf-8"?>
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?colorControlHighlight">
<item android:drawable="@drawable/image" />
</ripple>
或<FrameLayout>
属性的比较。