web-dev-qa-db-fra.com

Est-ce une mauvaise pratique d'utiliser des marges négatives dans Android?

Démo de marge négative:

 enter image description here

Le scénario

Chevauchement de vues en définissant une marge négative sur l’une d’elles afin qu’elle envahisse le cadre de sélection d’une autre vue.

Pensées

Cela semble fonctionner comme prévu avec un chevauchement des dispositions si elles le devraient. Mais je ne veux pas me heurter à un problème plus grave parce que, inconsciemment, nous ne faisons pas les choses correctement. Emulateurs, périphériques physiques, nommez-vous, lorsque vous utilisez des marges négatives, tout semble fonctionner correctement, une vue envahit le cadre de sélection des autres vues et, selon la façon dont elle est déclarée dans la présentation, elle sera située au-dessus ou au-dessous de l'autre vue.

Je sais aussi que, depuis l’API 21, nous pouvons définir les attributs translationZ et elevation pour que la vue apparaisse au-dessus ou au-dessous d’autres vues, mais ma préoccupation provient essentiellement du fait que dans la documentation pour les attributs layout_margin, il est clairement spécifié que les valeurs margin doivent être positives, laissez-moi vous citer:

Extrait:
Spécifie l'espace supplémentaire à gauche, en haut, à droite et en bas de cette vue. Cet espace est en dehors des limites de cette vue. Les valeurs de la marge doivent être positives . Doit être une valeur de dimension, qui est un nombre à virgule flottante ajouté avec une unité telle que "14.5sp". Les unités disponibles sont: px (pixels), dp (pixels indépendants de la densité), sp (pixels redimensionnés en fonction de la taille de police préférée), in (pouces), mm (millimètres). ) ...

Depuis que je pose cette question depuis des années, je n’ai jamais eu de problèmes de marges négatives, j’ai essayé d’éviter de les utiliser le plus possible, mais j’ai rencontré [pas] de problèmes, alors même si la documentation le dit, ne suis pas trop inquiet à ce sujet.

99
Juan Cortés

En 2010, @RomainGuy (ingénieur principal d'Android) a déclaré que les marges négatives avaient un comportement non spécifié .

En 2011, @RomainGuy a déclaré que vous pouvez utiliser des marges négatives sur LinearLayout et RelativeLayout .

En 2016, @RomainGuy a déclaré que ils n'ont jamais été officiellement pris en charge et ne seront pas pris en charge par ConstraintLayout

Il est cependant facile de contourner cette limitation. 

Ajoutez une vue d'assistance (hauteur 0dp, largeur limitée au parent) en bas de la vue de base, en bas, ajoutez la marge souhaitée.
Placez ensuite votre vue en dessous de celle-ci, ce qui lui permettra d’avoir une marge «négative» mais sans avoir à utiliser de valeur négative non prise en charge. 

166
CommonsWare

Si vous souhaitez utiliser une marge négative, définissez une marge suffisante pour le conteneur et son clipToPadding sur false et définissez une marge négative pour ses enfants afin de ne pas couper la vue enfant!

14
Ali

J'espère que cela aidera quelqu'un. Voici un exemple de code fonctionnel utilisant ConstraintLayout basé sur la réponse de @ CommonsWare:

Ajoutez une vue d’aide (hauteur 0dp, largeur limitée au parent) au niveau du fichier bas de la vue de base, en bas, ajoutez la marge souhaitée. Ensuite positionnez votre vue en dessous de celle-ci, en lui permettant effectivement d’avoir un marge "négative" mais sans avoir à utiliser de valeur négative non prise en charge valeur.

Exemple de code:

<TextView
    Android:id="@+id/below"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:background="#F1B36D"
    Android:padding="30dp"
    Android:text="I'm below"
    Android:textColor="#ffffff"
    Android:textSize="48sp"
    Android:textAlignment="center"
    tools:layout_editor_absoluteX="129dp"
    tools:layout_editor_absoluteY="0dp" />

<Android.support.v4.widget.Space
    Android:id="@+id/space"
    Android:layout_width="0dp"
    Android:layout_height="0dp"
    Android:layout_marginBottom="32dp"
    app:layout_constraintBottom_toBottomOf="@+id/below"
    app:layout_constraintLeft_toLeftOf="@id/below"
    app:layout_constraintRight_toRightOf="@id/below" />

<TextView
    Android:id="@+id/top"
    Android:layout_width="100dp"
    Android:layout_height="60dp"
    Android:textAlignment="center"
    Android:textColor="#ffffff"
    Android:text="I'M ON TOP!"
    Android:background="#676563"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/space" />

Sortie:

 enter image description here

5
VicJordan

C'était peut-être une mauvaise pratique dans le passé, mais avec Material Design et ses boutons d'action flottants, cela semble être inévitable et nécessaire dans de nombreux cas maintenant. Fondamentalement, lorsque vous avez deux mises en page distinctes que vous ne pouvez pas mettre dans un seul RelativeLayout car elles nécessitent une gestion distincte (par exemple, pensez à l'en-tête et au contenu), le seul moyen de chevaucher le FAB est de le faire ressortir mises en page utilisant des marges négatives. Et cela crée des problèmes supplémentaires avec les zones cliquables.

4
Gábor

Pour moi, et en ce qui concerne la définition d'une marge négative sur un TextView (je réalise que l'OP fait référence à un ViewGroup, mais je cherchais des problèmes de configuration des marges négatives et j'ai atterri ici) ... ... j'ai trouvé un problème avec 4.0.3 ( API 15) UNIQUEMENT et le réglage de Android:layout_marginTop ou Android:layout_marginBottom sur une valeur négative telle que -2dp.

Pour une raison quelconque, TextView ne s’affiche pas du tout. Il semble être "parti" de la vue (pas seulement invisible).

Quand j'ai essayé ceci avec les 3 autres versions de layout_margin, je n'ai pas vu le problème.

Notez que je n’ai pas essayé cela sur un vrai périphérique, c’est avec un émulateur 4.0.3. C’est la deuxième chose étrange que j’ai trouvée qui ne concerne que la version 4.0.3; ma nouvelle règle est donc de: toujours test avec un émulateur 4.0.3 :)

J'ai réussi à réduire la marge inférieure d'un TextView en utilisant Android:lineSpacingExtra="-2dp" qui fonctionne même si j'ai Android:singleLine="true" (et je n'aurais donc pas pensé que l'interlignage serait un facteur).

3
GaryAmundson

Non, vous ne devriez pas utiliser negative margin. vous devriez plutôt utiliser translate. Même si la marge négative fonctionne parfois, lorsque vous modifiez la mise en page de manière programmée, la traduction serait utile. Et la vue ne peut pas déborder de l'écran lorsque vous utilisez la marge.

1
Cheung Sean

J'ai seulement su que c'était possible pour une période assez courte. Mais je ne vois aucun problème avec cela. Soyez simplement conscient des tailles d'écran et autres afin d'éviter de créer accidentellement des éléments qui ne doivent pas apparaître superposés à l'écran. (c'est-à-dire que le texte en haut du texte est probablement une mauvaise idée.)

0
FoamyGuy