Jetez un coup d'oeil à cette petite application 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" />
L'image pointée par Android:foreground
n'est pas affichée, mais elle apparaît si je change foreground
en src
ou background
dans activity_main.xml
. Ce code semble suivre les instructions décrites ici:
https://developer.Android.com/reference/Android/view/View.html#attr_Android:foreground
Pourquoi la balise Android:foreground
ne fonctionne-t-elle pas dans le code ci-dessus?
REMARQUE:
minSdkVersion
est 19
, je lance cette application sur Android 5.1
(API level 22
)
Ceci est dû à un bug existant dans Android depuis le niveau 23 de l'API.
Voici la liste de toutes les méthodes et des attributs XML correspondants liés à la définition de vues dessinables au premier plan avec les niveaux d'API introduits via FrameLayout
. Cependant, ceux-ci sont plus tard déplacés dans View
dans l'API de niveau 23.
╔════════════════════════════╦═════════════════════════════════════════════════╦═════════════╗
║ Methods ║ XML attributes ║ ║
║ ║ ║ 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 ║
╚════════════════════════════╩═════════════════════════════════════════════════╩═════════════╝
La documentation Android indique que setForeground(Drawable)
est ajouté dans l’API 1 et que setForegroundTintList (ColorStateList tint)
et setForegroundTintMode (PorterDuff.Mode tintMode)
sont ajoutés dans l’API de niveau 21 en View
. Il est faux. Il y en avait dans FrameLayout
jusqu'à l'API 23.
Au niveau de l'API <23, vous recevrez un avertissement même s'il n'est pas requis. Vous pouvez simplement le supprimer. Voir this .
Examinons maintenant comment ces propriétés fonctionnent sur différentes versions.
╔═══════════╦══════════════════╦══════════════════╗
║ API level ║ By code ║ Using XML ║
╠═══════════╬══════════════════╬══════════════════╣
║ <23 ║ FrameLayout only ║ FrameLayout only ║
╠═══════════╬══════════════════╬══════════════════╣
║ >=23 ║ FrameLayout only ║ All views ║
╚═══════════╩══════════════════╩══════════════════╝
Lorsque ces propriétés ont été déplacées à View
dans l'API de niveau 23, elles ont apporté des modifications étranges qui peuvent être appelées un bogue. Lors du chargement des propriétés à partir de XML, il vérifie si la View
est une FrameLayout
qui n'est pas présente dans les méthodes que nous pouvons utiliser dans le même but.
Constructeur de vue, niveau 23 de l'API:
case R.styleable.View_foreground:
if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
setForeground(a.getDrawable(attr));
}
break;
Pour utiliser Android:foreground
sur Android 5.1
c'est-à-dire API level 22
, vous n'utilisez pas Android:foreground
.
Comme son nom indique clairement que vous pouvez définir le dessin sur le dessus/le premier plan de tout contenu tel que la superposition, c’est-à-dire que vous pouvez placer une vue dans FrameLayout
dans laquelle vous pouvez utiliser Android:foreground
. Dans cette FrameLayout, ajoutez votre ImageView
.
Définit le dessinable à dessiner sur le contenu. Ceci peut être utilisé comme une superposition. Le premier plan dessinable participe au rembourrage de le contenu si la gravité est définie pour se remplir.
Voici un exemple d'utilisation:
<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>
Remarque: Pour API level > 23
, cela fonctionnera sans FrameLayout
.
J'espère que cela t'aidera.
Il semble qu’à un moment donné (API <23), Android:foreground
ne fonctionnerait qu’avec FrameLayout
, comme le suggère VicJordan. Cependant, pour l’API 23+, il apparaît que Android:foreground
fonctionnera pour tout type de vue. Voir this selection de la source View.Java:
case R.styleable.View_foreground:
if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
setForeground(a.getDrawable(attr));
}
Voici un exemple de Android:foreground
travaillant sur l'API 28 avec la présentation suivante:
<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>
Pourtant, sur API 22, nous voyons ceci:
Aucune image de premier plan. Donc, Android:foreground
ne fonctionne que lorsque le niveau de l'API est de 23+. Je conviens que cela n’est pas vraiment documenté, mais c’est comme ça.
Update: API 23 semble avoir un problème avec Android:foreground
, alors supposons que Android:foreground
fonctionne sur API 24+ pour les vues générales.
Deuxième mise à jour: Je suis tombé sur quelques articles traitant de la même question concernant setForeground()
ici et ici . Dans la réponse acceptée à la deuxième question, CommonsWare identifie cela comme un "bogue de documentation".