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


114

Démo de marge négative:

                         entrez la description de l'image ici

Le scénario

Chevauchement de vues en définissant une marge négative sur l'une d'entre elles afin qu'elle envahisse le cadre englobant d'une autre vue.

Pensées

Cela semble fonctionner comme vous vous attendez avec le chevauchement des mises en page si elles le devraient. Mais je ne veux pas me heurter à un problème plus grave pour ne pas faire les choses correctement sans le savoir. Émulateurs, périphériques physiques, nommez-le, lorsque vous utilisez des marges négatives, tout semble fonctionner correctement, une vue envahit la zone de délimitation des vues d'une autre et selon la façon dont elle est déclarée dans la mise en page, elle sera au-dessus ou en dessous de l'autre vue.

Je suis également conscient que depuis l'API 21, nous pouvons définir les attributs translationZet elevationpour faire apparaître la vue au-dessus ou en dessous d'autres vues, mais mon inquiétude vient essentiellement du fait que dans la documentation des layout_marginattributs, il est clairement spécifié que les valeurs de marge doivent être positives , laissez moi cite:

Extrait:
spécifie un espace supplémentaire sur les côtés gauche, supérieur, droit et inférieur de cette vue. Cet espace est en dehors des limites de cette vue. Les valeurs de 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 mis à l'échelle en fonction de la taille de police préférée), in (pouces), mm (millimètres) ...

Au cours des années à l' origine de cette demande question que je ne l' ai pas eu de problèmes avec des marges négatives, ont essayé d'éviter de les utiliser autant que possible, mais ne pas rencontré de problèmes, de sorte que même si les états de documentation, je ne suis pas trop inquiet à ce sujet.


1
Je sais que les tests d'espresso ne pourront pas voir l'objet si l'une de ses marges est négative ... c'est donc une raison de ne pas les utiliser
Tim Boland

Réponses:


192

En 2010, @RomainGuy (ingénieur Android principal) 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 LinearLayoutetRelativeLayout .

En 2016, @RomainGuy a déclaré qu'ils n'avaient jamais été officiellement pris en charge et ne seraient pas pris en charge parConstraintLayout .

Il est cependant facile de contourner cette limitation.

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


1
Cela semble être une chose inoffensive alors, laisser ouverte au cas où quelqu'un aurait un autre aperçu
Juan Cortés

1
@DrewLeSueur: Je ne ferais pas cette hypothèse. Je n'ai aucune idée de ce que signifierait même un rembourrage négatif.
CommonsWare

1
@CommonsWare pouvez-vous me dire, est-il possible de faire quelque chose comme ça `- @ dimen / anyvalue"? Je veux appeler la valeur déclarée mais négative. Aide.
deadfish

2
@ 100kg: Désolé, mais ce n'est pas pris en charge.
CommonsWare

21
J'ai remarqué que dans Android 4.4 KitKat, quelque chose a changé en ce qui concerne les marges négatives (par rapport à 4.3; au moins sur Asus Nexus 7). Il s'avère que vous avez besoin android:clipChildren="false"et android:clipToPadding="false"où vous ne l'avez pas fait auparavant, ou les choses se cassent comme ça .
Jonik

18

J'espère que cela aidera quelqu'un. Voici un exemple de code de travail ConstraintLayoutbasé sur la réponse de @ CommonsWare:

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

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" />

Production:

entrez la description de l'image ici


16

Si vous souhaitez utiliser une marge négative, définissez suffisamment de remplissage 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!


4

Cela aurait pu ê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 (pensez à l'en-tête et au contenu, par exemple), le seul moyen de chevaucher le FAB est de le faire dépasser d'un de ces mises en page utilisant des marges négatives. Et cela crée des problèmes supplémentaires avec les zones cliquables.


3

Pour moi, et concernant la définition d'une marge négative sur un TextView (je me rends compte que l'OP fait référence à un ViewGroup, mais je cherchais des problèmes avec la définition de 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_marginTopou android:layout_marginBottomà 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é cela 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 appareil réel, cela utilise un émulateur 4.0.3. C'est la deuxième chose étrange que j'ai trouvée qui n'affectait que la version 4.0.3, donc ma nouvelle règle est de toujours tester avec un émulateur 4.0.3 :)

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


1
J'ai trouvé un comportement similaire sur un Nexus 4 (qui est xhdpi) et 4.2.2. Il y avait une mise en page sans remplissage, même si une mise en page parent avait un remplissage. Il y avait un TextView à l'intérieur avec un marginTop négatif. Sur 5.0, cela fonctionnait bien. Sur 4.2.2 à la fois sur l'appareil et dans un émulateur pour Nexus 4, il disparaît. La solution consistait à déplacer le remplissage vers la disposition qui contenait le TextView.
louielouie

3

Non, vous ne devriez pas utiliser negative margin. à la place, vous devriez 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 vous aidera. Et la vue ne peut pas déborder de l'écran lorsque vous utilisez la marge.


0

Je savais seulement que c'était possible pendant une période assez courte. Mais je n'y vois aucun problème. Soyez juste conscient de la taille de l'écran et ainsi de suite afin de ne pas créer accidentellement des éléments qui ne devraient pas apparaître superposés à l'écran. (c'est-à-dire que le texte au-dessus du texte est probablement une mauvaise idée.)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.