Ist es eine schlechte Praxis, in Android negative Ränder zu verwenden?

114

Demo der negativen Marge:

                         Geben Sie hier die Bildbeschreibung ein

Das Szenario

Überlappende Ansichten, indem für einen von ihnen ein negativer Rand festgelegt wird, sodass er in den Begrenzungsrahmen einer anderen Ansicht eindringt.

Gedanken

Es scheint so zu funktionieren, wie Sie es von einer Überlappung der Layouts erwarten würden, wenn sie sollten. Aber ich möchte nicht auf ein größeres Problem stoßen, weil ich unwissentlich die Dinge nicht richtig mache. Emulatoren, physische Geräte, wie Sie es nennen, wenn Sie negative Ränder verwenden, scheint alles korrekt zu funktionieren, eine Ansicht greift in den Begrenzungsrahmen einer anderen Ansicht ein und befindet sich je nach Deklaration im Layout über oder unter der anderen Ansicht.

Ich bin mir auch bewusst, dass wir seit API 21 die Attribute translationZund festlegen können elevation, damit die Ansicht über oder unter anderen Ansichten angezeigt wird. Mein Anliegen beruht jedoch im Wesentlichen auf der Tatsache, dass in der Dokumentation zu den layout_marginAttributen klar angegeben ist, dass die Randwerte positiv sein sollten ich zitiere:

Auszug:
Gibt zusätzlichen Platz auf der linken, oberen, rechten und unteren Seite dieser Ansicht an. Dieser Bereich befindet sich außerhalb der Grenzen dieser Ansicht. Die Margin-Werte sollten positiv sein . Muss ein Dimensionswert sein, bei dem es sich um eine Gleitkommazahl handelt, an die eine Einheit wie "14.5sp" angehängt ist. Verfügbare Einheiten sind: px (Pixel), dp (dichteunabhängige Pixel), sp (skalierte Pixel basierend auf der bevorzugten Schriftgröße), in (Zoll), mm (Millimeter) ...

In den Jahren seit ursprünglich diese Frage habe ich keine Probleme hatte mit negativen Margen, versuchen mit ihnen so viel wie möglich zu vermeiden, aber habe nicht alle Probleme, die so , obwohl die Dokumentation besagt , dass, ich bin auch nicht besorgt darüber.

Juan Cortés
quelle
1
Ich weiß, dass Espressotests das Objekt nicht sehen können, wenn einer seiner Ränder negativ ist ... das ist ein Grund, sie nicht zu verwenden
Tim Boland

Antworten:

192

Im Jahr 2010 gab @RomainGuy (Core Android Engineer) an, dass negative Margen ein nicht spezifiziertes Verhalten aufweisen .

Im Jahr 2011 gab @RomainGuy an, dass Sie negative Ränder für LinearLayoutund verwenden könnenRelativeLayout .

Im Jahr 2016 gab @RomainGuy an, dass sie nie offiziell unterstützt wurden und von nicht unterstützt werdenConstraintLayout .

Es ist jedoch einfach, diese Einschränkung zu umgehen.

Fügen Sie am unteren Rand Ihrer Basisansicht eine Hilfsansicht hinzu (Höhe 0 dp, Breite auf übergeordnet), und fügen Sie unten den gewünschten Rand hinzu.
Positionieren Sie dann Ihre Ansicht unter dieser, sodass sie einen "negativen" Rand aufweist, ohne jedoch einen nicht unterstützten negativen Wert verwenden zu müssen.

CommonsWare
quelle
1
Scheint dann eine harmlose Sache zu sein, offen zu lassen, falls jemand andere Einsichten hat
Juan Cortés
1
@DrewLeSueur: Ich würde diese Annahme nicht machen. Ich habe keine Ahnung, was eine negative Polsterung überhaupt bedeuten würde.
CommonsWare
1
@ CommonsWare können Sie mir sagen, ist es möglich, so etwas zu tun `- @ dimen / anyvalue"? Ich möchte deklarierten Wert aber negativ anrufen. Hilfe.
Deadfish
2
@ 100kg: Sorry, aber das wird nicht unterstützt.
CommonsWare
21
Ich habe festgestellt, dass sich in Android 4.4 KitKat etwas in Bezug auf negative Ränder geändert hat (im Vergleich zu 4.3; zumindest bei Asus Nexus 7). Es stellt sich heraus, dass Sie brauchen android:clipChildren="false"und android:clipToPadding="false"wo Sie es vorher nicht getan haben, oder Dinge brechen so .
Jonik
18

Hoffe das wird jemandem helfen. Hier ist ein Beispielcode, ConstraintLayoutder auf der Antwort von @ CommonsWare basiert:

Fügen Sie am unteren Rand Ihrer Basisansicht eine Hilfsansicht hinzu (Höhe 0 dp, Breite auf übergeordnet), und fügen Sie unten den gewünschten Rand hinzu. Positionieren Sie dann Ihre Ansicht unter dieser, sodass sie einen "negativen" Rand aufweist, ohne jedoch einen nicht unterstützten negativen Wert verwenden zu müssen.

Beispielcode:

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

Ausgabe:

Geben Sie hier die Bildbeschreibung ein

Vikasdeep Singh
quelle
16

Wenn Sie einen negativen Rand verwenden möchten, setzen Sie genügend Abstand für den Container und dessen clipToPadding auf false und setzen Sie einen negativen Rand für die untergeordneten Elemente , damit die untergeordnete Ansicht nicht abgeschnitten wird!

Ali
quelle
4

Es mag in der Vergangenheit eine schlechte Praxis gewesen sein, aber mit Material Design und seinen schwebenden Aktionstasten scheint es unvermeidlich und in vielen Fällen jetzt erforderlich zu sein. Wenn Sie zwei separate Layouts haben, die Sie nicht in ein einzelnes RelativeLayout einfügen können, weil sie eine deutlich getrennte Behandlung erfordern (z. B. Header und Inhalt), besteht die einzige Möglichkeit, das FAB zu überlappen, darin, es aus einem herauszuhalten Layouts mit negativen Rändern. Dies führt zu zusätzlichen Problemen mit anklickbaren Bereichen.

Gábor
quelle
3

Für mich und in Bezug auf das Festlegen eines negativen Randes in einer Textansicht (mir ist klar, dass sich das OP auf eine ViewGroup bezieht, aber ich habe nach Problemen beim Festlegen negativer Ränder gesucht und bin hier gelandet) ... Ich habe ein Problem mit 4.0.3 gefunden ( API 15) NUR und die Einstellung von android:layout_marginTopoder android:layout_marginBottomauf einen negativen Wert wie -2dp.

Aus irgendeinem Grund wird die Textansicht überhaupt nicht angezeigt. Es scheint aus der Ansicht "verschwunden" zu sein (nicht nur unsichtbar).

Als ich dies mit den anderen 3 Versionen von layout_margin versuchte, sah ich das Problem nicht.

Beachten Sie, dass ich dies auf einem realen Gerät nicht ausprobiert habe. Es wird ein 4.0.3-Emulator verwendet. Dies ist die zweite seltsame Sache, die ich gefunden habe und die nur 4.0.3 betroffen hat. Meine neue Regel lautet also, immer mit einem 4.0.3-Emulator zu testen :)

Ich habe Erfolg damit, den unteren Rand einer Textansicht zu reduzieren, indem android:lineSpacingExtra="-2dp"ich verwende, was funktioniert, obwohl ich es zufällig habe android:singleLine="true"(und daher hätte ich nicht gedacht, dass der Zeilenabstand ein Faktor sein würde).

GaryAmundson
quelle
1
Ich fand ein ähnliches Verhalten auf einem Nexus 4 (xhdpi) und 4.2.2. Es gab ein Layout ohne Polsterung, obwohl ein übergeordnetes Layout Polsterung hatte. Es gab eine Textansicht mit negativem marginTop. Auf 5.0 hat es gut funktioniert. In 4.2.2 auf dem Gerät und in einem Emulator für Nexus 4 verschwindet es. Die Lösung bestand darin, die Polsterung in das Layout zu verschieben, das die Textansicht enthielt.
Louielouie
3

Nein, du solltest nicht verwenden negative margin. stattdessen solltest du verwendentranslate . Selbst wenn ein negativer Rand irgendwann funktioniert, wenn Sie das Layout programmierbar ändern, hilft die Übersetzung. Und die Ansicht kann den Bildschirm nicht überlaufen, wenn Sie den Rand verwenden.

Cheung Sean
quelle
0

Ich habe nur gewusst, dass es für einen relativ kurzen Zeitraum möglich war. Aber ich sehe kein Problem damit. Achten Sie nur auf die Bildschirmgrößen und dergleichen, damit Sie nicht versehentlich Elemente bearbeiten, die auf dem Bildschirm nicht überlappen sollten. (dh Text über Text ist wahrscheinlich eine schlechte Idee.)

FoamyGuy
quelle