Definieren der Z-Reihenfolge der Ansichten von RelativeLayout in Android

226

Ich möchte die z-Reihenfolge der Ansichten eines RelativeLayout in Android definieren.

Ich weiß, dass ein Weg, dies zu tun, das Anrufen ist bringToFront.

Gibt es einen besseren Weg, dies zu tun? Es wäre toll, wenn ich die z-Reihenfolge in der Layout-XML definieren könnte.

hpique
quelle
4
View.bringToFront (); ist der anser
Shirish Herwade

Antworten:

314

Am einfachsten ist es, auf die Reihenfolge zu achten, in der die Ansichten zu Ihrer XML-Datei hinzugefügt werden. Niedriger unten in der Datei bedeutet höher oben in der Z-Achse.

Bearbeiten: Dies ist hier und hier auf der Android-Entwicklerseite dokumentiert . (Danke @flightplanner)

Steve Haley
quelle
16
Dies kann leider nicht immer geändert werden. Zum Beispiel können in einem relativen Layout jedes Element nur in Bezug auf die zuvor in der Datei definierten Elemente angeordnet werden
Casebash
67
Casebash, ich denke nicht, dass dies notwendigerweise der Fall ist. Sie müssen nur die "@ + id / your_element_before_its_defined" verwenden und dann dieselbe ID in dem Element verwenden, das Sie später definieren. Ich könnte mich irren, diese Layouts sind sehr schwierig für mich, aber ich habe definitiv den Eindruck, dass es funktioniert.
2.
7
tjb hat recht (und ich bin froh, dass er es ist). Verwenden Sie @ + id mit der allerersten Erwähnung der ID, z. B. layout_above = "@ + id / some_id"
Michiel
3
Sie können auch <item type = "id" name = "<Ihre_ID>" /> in eine XML-Wertedatei einfügen und dann überall darauf verweisen.
karl
8
Ich weiß , ich bin etwa 3 Jahre zu spät zur Party, aber in der Antwort auf @hpique wird dies dokumentiert hier
HexAndBugs
88

Wenn Sie dies im Code tun möchten, können Sie dies tun

View.bringToFront();

siehe docs

QAMAR
quelle
68

Bitte beachten Sie, dass Schaltflächen und andere Elemente in API 21 und höher eine hohe Höhe haben und daher die XML-Reihenfolge der Elemente unabhängig vom übergeordneten Layout ignorieren. Ich habe eine Weile gebraucht, um das herauszufinden.

Daniel Wilson
quelle
16
Die Lösung für diesen Fehler bestand für mich darin, setElevation (1000) für die Ansicht aufzurufen, die über die Schaltfläche gerendert werden soll.
Feuer im Loch
setElevation () erfordert API-Level 21
dp2050
21

In Android ab API-Ebene 21 erhalten Elemente in der Layoutdatei ihre Z-Reihenfolge sowohl anhand der Reihenfolge in der Datei, wie in der richtigen Antwort beschrieben, als auch anhand ihrer Höhe. Ein höherer Höhenwert bedeutet, dass das Element eine höhere Z-Reihenfolge erhält .

Dies kann manchmal zu Problemen führen, insbesondere bei Schaltflächen, die häufig über Elementen angezeigt werden, die gemäß der Reihenfolge des XML in der Z-Reihenfolge darunter liegen sollten. Um dies zu beheben, stellen Sie einfach android:elevationdie Elemente in Ihrem Layout-XML so ein, dass sie der Z-Reihenfolge entsprechen, die Sie erreichen möchten.

Wenn Sie eine Höhe eines Elements im Layout festlegen, wird ein Schatten geworfen. Wenn Sie diesen Effekt nicht möchten, können Sie den Schatten mit folgendem Code entfernen:

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

Ich habe keine Möglichkeit gefunden, den Schatten einer erhöhten Ansicht durch die Layout-XML zu entfernen.

lejonl
quelle
1
Wie in den Kommentaren erwähnt, können Sie verwenden android:elevation="1000dp". Auf diese Weise wird kein Schatten gerendert.
Vadim Kotov
15

Ich bin auf die gleichen Probleme gestoßen: In einem relativen Layout parentView habe ich zwei Kinder childView1 und childView2. Zuerst setze ich childView1 über childView2 und möchte, dass childView1 über childView2 liegt. Das Ändern der Reihenfolge der Ansichten von Kindern hat das Problem für mich nicht gelöst. Was für mich funktioniert hat, ist android: clipChildren = "false" in parentView und in dem von mir festgelegten Code zu setzen:

childView1.bringToFront();

parentView.invalidate();
Tony Vu
quelle
2
Das funktioniert und Android macht mich so traurig. child.bringToFront()mit parent.invalidate()Werken, aber parent.bringChildToFront(child)nicht. Wo ist die Logik, die wir alle von einem Betriebssystem erwarten?
Oliver Hausler
Um einige Ansichten zu animieren (Übersetzungen in X und Y), habe ich verschiedene Kombinationen für LinearLayout, FrameLayout und RelativeLayout ausprobiert, aber es gab immer Probleme (im Zusammenhang mit Überlappungen oder nicht proportionalen Größen). Endlich android:clipChildren="false"hat es geschafft. Danke dir!
JCarlosR
15

Bitte beachten Sie, dass Sie view.setZ(float)ab API-Level 21 verwenden können. Hier finden Sie weitere Informationen.

Vadim Kotov
quelle
13

Ich dachte, ich würde seit der Einführung des eine Antwort hinzufügen

android: translationZ

Das XML-Feld hat die Dinge ein wenig verändert. Die anderen Antworten, die das Laufen vorschlagen

childView1.bringToFront();

parentView.invalidate();

sind absolut genau richtig, AUSSER, dass dieser Code childView1 NICHT vor eine Ansicht mit einem fest codierten android: translationZ in der XML-Datei bringt. Ich hatte Probleme damit und nachdem ich dieses Feld aus den anderen Ansichten entfernt hatte, funktionierte bringToFront () einwandfrei.

ThePartyTurtle
quelle
Dies gilt auch für die Android 5'selevation
Shelll
5

API 21 hat view.setElevation(float)build-in

Zur ViewCompat.setElevation(view, float);Abwärtskompatibilität verwenden

Weitere Methoden ViewCompat.setZ(v, pixels)undViewCompat.setTranslationZ(v, pixels)

Auf andere Weise können Sie Schaltflächen sammeln oder ein Array anzeigen und addViewzum Hinzufügen zu RelativeLayout verwenden

Qamar
quelle
1

Sie können benutzerdefinierte RelativeLayoutmit neu definierten verwenden

protected int getChildDrawingOrder (int childCount, int i)

Beachten Sie, dass bei dieser Methode param ials "welche Ansicht soll ich zeichnen i'th" verwendet wird. So ViewPagerfunktioniert es. Es legt die benutzerdefinierte Zeichenreihenfolge in Verbindung mit fest PageTransformer.

Petrov Dmitrii
quelle
0

Überprüfen Sie, ob in einer der Ansichten in XML eine Höhe vorhanden ist. Wenn ja, fügen Sie dem anderen Element eine Höhe hinzu oder entfernen Sie die Höhe, um das Problem zu beheben. Von dort aus ist es die Reihenfolge der Ansichten, die bestimmt, was über dem anderen steht.

Der flauschige T Rex
quelle
0

Oder fügen Sie die überlappende Schaltfläche oder Ansichten in ein FrameLayout ein. Dann berücksichtigt das RelativeLayout in der XML-Datei die Reihenfolge der untergeordneten Layouts, die hinzugefügt wurden.

Badr
quelle
0

Sie können das folgende Codebeispiel auch verwenden, um dasselbe zu erreichen

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

Dies ist abwärtskompatibel. Hier mCardViewist eine Ansicht, die unten sein sollte sourceView.

Ankit
quelle