Définition de l'ordre Z des vues de RelativeLayout dans Android

226

Je voudrais définir l'ordre z des vues d'un RelativeLayout dans Android.

Je sais qu'une façon de le faire est d'appeler bringToFront.

Existe-t-il une meilleure façon de procéder? Ce serait génial si je pouvais définir l'ordre z dans la mise en page xml.

hpique
la source
4
View.bringToFront (); est l'anser
Shirish Herwade

Réponses:

314

Le moyen le plus simple consiste simplement à faire attention à l'ordre dans lequel les vues sont ajoutées à votre fichier XML. Plus bas dans le fichier signifie plus haut dans l'axe Z.

Modifier: Ceci est documenté ici et ici sur le site des développeurs Android. (Merci @flightplanner)

Steve Haley
la source
16
Ce n'est malheureusement pas toujours possible de changer. Par exemple, dans une disposition relative, chaque élément ne peut être disposé que par rapport à ceux précédemment définis dans le fichier
Casebash
67
Casebash, je ne pense pas que ce soit nécessairement le cas, il vous suffit d'utiliser le "@ + id / your_element_before_its_defined", puis d'utiliser le même identifiant dans l'élément que vous définissez plus tard. Je peux me tromper à ce sujet, ces dispositions sont très difficiles pour moi, mais j'ai vraiment l'impression que cela fonctionne.
tjb
7
tjb a raison (et je suis content qu'il le soit). Utilisez @ + id avec la toute première mention de l'identifiant, par exemple layout_above = "@ + id / some_id"
Michiel
3
Vous pouvez également mettre <item type = "id" name = "<your_id>" /> dans un fichier xml de valeurs, puis vous pouvez le référencer n'importe où.
karl
8
Je sais que j'ai environ 3 ans de retard pour la fête, mais en réponse à @hpique, cela est documenté ici
HexAndBugs
88

Si vous voulez le faire dans le code, vous pouvez le faire

View.bringToFront();

voir les documents

QAMAR
la source
68

Veuillez noter que les boutons et autres éléments de l'API 21 et supérieur ont une élévation élevée et ignorent donc l'ordre xml des éléments, quelle que soit la disposition parent. Cela m'a pris un certain temps pour comprendre celui-là.

Daniel Wilson
la source
16
la solution à ce bogue pour moi a été d'appeler setElevation (1000) sur la vue que je veux voir sur le bouton.
feu dans le trou
setElevation () nécessite le niveau d'API 21
dp2050
21

Dans Android à partir du niveau 21 de l'API, les éléments du fichier de disposition obtiennent leur ordre Z à la fois de la façon dont ils sont ordonnés dans le fichier, comme décrit dans la bonne réponse, et de leur élévation, une valeur d'élévation plus élevée signifie que l'élément obtient un ordre Z plus élevé .

Cela peut parfois causer des problèmes, en particulier avec les boutons qui apparaissent souvent au-dessus des éléments qui, selon l'ordre du XML, doivent être en dessous d'eux dans l'ordre Z. Pour résoudre ce problème, définissez simplement android:elevationles éléments de votre mise en page XML pour qu'ils correspondent à l'ordre Z que vous souhaitez atteindre.

Si vous définissez une élévation d'un élément dans la mise en page, il commencera à projeter une ombre. Si vous ne voulez pas de cet effet, vous pouvez supprimer l'ombre avec du code comme ceci:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   myView.setOutlineProvider(null);
}

Je n'ai trouvé aucun moyen de supprimer l'ombre d'une vue élevée à travers le xml de mise en page.

lejonl
la source
1
Comme mentionné dans les commentaires, vous pouvez utiliser android:elevation="1000dp". Aucune ombre n'est rendue de cette façon.
Vadim Kotov
15

J'ai rencontré les mêmes problèmes: dans un parentView de disposition relative, j'ai 2 enfants childView1 et childView2. Au début, je mets childView1 au-dessus de childView2 et je veux que childView1 soit au-dessus de childView2. Changer l'ordre des vues des enfants n'a pas résolu le problème pour moi. Ce qui a fonctionné pour moi, c'est de définir android: clipChildren = "false" sur parentView et dans le code que j'ai défini:

childView1.bringToFront();

parentView.invalidate();
Tony Vu
la source
2
Cela fonctionne et Android me rend si triste. child.bringToFront()avec des parent.invalidate()œuvres, mais parent.bringChildToFront(child)ne le fait pas. Où est la logique que nous attendons tous d'un OS?
Oliver Hausler
Afin d'animer certaines vues (traductions en X et Y), j'ai essayé plusieurs combinaisons pour LinearLayout, FrameLayout et RelativeLayout mais il y avait toujours des problèmes (liés aux chevauchements ou aux tailles non proportionnelles). Enfin android:clipChildren="false"fait l'affaire. Je vous remercie!
JCarlosR
15

S'il vous plaît noter que vous pouvez utiliser à view.setZ(float)partir du niveau de l' API 21. Ici , vous pouvez trouver plus d' informations.

Vadim Kotov
la source
13

J'ai pensé ajouter une réponse depuis l'introduction du

android: translationZ

Le champ XML a changé les choses un peu. Les autres réponses qui suggèrent de courir

childView1.bringToFront();

parentView.invalidate();

sont totalement parfaits SAUF que ce code ne mettra PAS childView1 devant aucune vue avec un android codé en dur: translationZ dans le fichier XML. J'avais des problèmes avec cela, et une fois que j'ai supprimé ce champ des autres vues, bringToFront () a très bien fonctionné.

ThePartyTurtle
la source
cela est également vrai pour les android 5elevation
shelll
5

API 21 a view.setElevation(float)intégré

Utiliser ViewCompat.setElevation(view, float);pour la compatibilité descendante

Plus de méthodes ViewCompat.setZ(v, pixels)etViewCompat.setTranslationZ(v, pixels)

Une autre façon de collecter des boutons ou d'afficher un tableau et de l'utiliser addViewpour ajouter à RelativeLayout

Qamar
la source
1

Vous pouvez utiliser personnalisé RelativeLayoutavec redéfini

protected int getChildDrawingOrder (int childCount, int i)

Soyez conscient - cette méthode prend param icomme "quelle vue dois-je dessiner i'th". Voilà comment ça ViewPagermarche. Il définit l'ordre de dessin personnalisé en conjonction avec PageTransformer.

Petrov Dmitrii
la source
0

Vérifiez si vous avez une élévation sur l'une des vues en XML. Si tel est le cas, ajoutez l'élévation à l'autre élément ou supprimez l'élévation pour résoudre le problème. De là, c'est l'ordre des vues qui dicte ce qui vient au-dessus de l'autre.

Le Fluffy T Rex
la source
0

Ou placez le bouton ou les vues qui se chevauchent dans un FrameLayout. Ensuite, le RelativeLayout dans le fichier xml respectera l'ordre des dispositions enfants lors de leur ajout.

Badr
la source
0

Vous pouvez également utiliser l'exemple de code ci-dessous pour obtenir le même

ViewCompat.setElevation(sourceView, ViewCompat.getElevation(mCardView)+1);

Ceci est rétrocompatible. Voici mCardViewune vue qui devrait être ci-dessous sourceView.

Ankit
la source