Short answer
This is due to a bug which existing in Android since API level 23.
More details on the behavior
Here is the list of all the XML attributes and corresponding methods related to setting foreground drawables to views with the API level they are introduced through FrameLayout
. However, these are later moved into View
in API level 23.
╔════════════════════════════╦═════════════════════════════════════════════════╦═════════════╗
║ 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 says setForeground(Drawable)
is added in API 1 and setForegroundTintList (ColorStateList tint)
and setForegroundTintMode (PorterDuff.Mode tintMode)
are added in API level 21 to View
. Actually they were there in FrameLayout
until it moved in API 23.
In API level < 23, you will get a warning even though it is not required. You can just suppress it. See this.
Now take a look at how these properties work on different versions.
╔═══════════╦══════════════════╦══════════════════╗
║ API level ║ By code ║ Using XML ║
╠═══════════╬══════════════════╬══════════════════╣
║ <23 ║ FrameLayout only ║ FrameLayout only ║
╠═══════════╬══════════════════╬══════════════════╣
║ >=23 ║ FrameLayout only ║ All views ║
╚═══════════╩══════════════════╩══════════════════╝
The cause of the bug
When these properties moved to View
in API level 23, they did some strange modifications on it which can be called a bug. While loading properties from XML, it checks whether the View
is a FrameLayout
which is not present inside the methods we can use for the same purpose.
View constructor, API level 23:
case R.styleable.View_foreground:
if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
setForeground(a.getDrawable(attr));
}
break;
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…