Wie kann man RelativeLayout mit Merge and Include zum Laufen bringen?

Lesezeit: 14 Minuten

Benutzer-Avatar
Justin

Ich versuche seit einigen Tagen, meine Layouts effizienter zu gestalten, indem ich von der Verwendung mehrerer Verschachtelungsebenen umstelle LinearLayouts zu eins RelativeLayout und bin auf ein paar Probleme gestoßen, für die ich keine Lösung gefunden habe …

Ich habe die Android-Anfängergruppe und diese Seite durchsucht und konnte nichts finden, was mir bei der Lösung des Problems helfen würde.

Ich habe in einem der Blogs gelesen, dass Sie Layouts mit Merge- und Include-Tags kombinieren können. Was ich also habe, ist eine Hauptlayoutdatei mit einer RelativeLayout Wurzelelement. Darin habe ich 5 Include-Tags, die auf 5 verschiedene XML-Layoutdateien verweisen, die jeweils ein Zusammenführungselement für den Stamm haben (alle meine Zusammenführungsdateien sind bis auf die darin enthaltenen IDs gleich).

Ich stoße auf zwei Probleme, die ich erklären werde, nachdem ich eine vereinfachte Version meines Layout-Codes gepostet habe:

Beispiel einer Hauptlayoutdatei:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/translucent_gray" >

    <include 
        android:id="@+id/running_gallery_layout_id"
        layout="@layout/running_gallery_layout" />

    <include 
        android:id="@+id/recent_gallery_layout_id" 
        layout="@layout/recent_gallery_layout"
        android:layout_below="@id/running_gallery_layout_id" />

    <include
        android:id="@+id/service_gallery_layout_id"
        layout="@layout/service_gallery_layout"
        android:layout_below="@id/recent_gallery_layout_id" />

    <include
        android:id="@+id/process_gallery_layout_id"
        layout="@layout/process_gallery_layout"
        android:layout_below="@id/service_gallery_layout_id" />

</RelativeLayout>

Beispiel enthaltene Zusammenführungsdatei:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView 
        style="@style/TitleText"
        android:id="@+id/service_gallery_title_text_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:text="@string/service_title" />

    <Gallery
        android:id="@+id/service_gallery_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_below="@id/service_gallery_title_text_id" />

    <TextView 
        style="@style/SubTitleText"
        android:id="@+id/service_gallery_current_text_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/service_gallery_title_text_id"
        android:layout_above="@id/service_gallery_id" />
</merge>

Ich stoße auf zwei Probleme:

1) Die android:layout_* Attribute scheinen ignoriert zu werden, wenn sie im include-Tag verwendet werden, und alle zusammengeführten Layouts werden übereinander angezeigt. Laut diesem Beitrag (http://developer.android.com/resources/articles/layout-tricks-reuse.html) “irgendein android:layout_* Attribut kann mit dem verwendet werden <include /> Schild”

2) Da ich das nicht zum Laufen bringen konnte, entschied ich mich, eine hinzuzufügen android:layout_below dem ersten zuschreiben TextView Element in jeder Merge-Layout-Datei, was bedeutet, dass jede Merge-Datei auf eine ID aus einer anderen Merge-Layout-Datei verweisen würde … Zum größten Teil hat dies tatsächlich funktioniert und mein Layout sieht gut aus. Allerdings bekomme ich einen Fehler bei einem der android:layout_below Attribute, die besagen, dass die von mir angegebene ID nicht gefunden werden kann … Ich habe die IDs doppelt und dreifach überprüft, um sicherzustellen, dass sie korrekt sind. Das Seltsamste daran ist, dass ich die verwendet habe AutoFill Funktion, um die ID überhaupt erst in das Attribut einzufügen.

Wenn jemand irgendwelche Vorschläge oder Problemumgehungen hat, werde ich mehr als glücklich sein, sie auszuprobieren. Wenn sich jemand eine Möglichkeit vorstellen kann, nur eine XML-Layoutdatei zusammenzuführen, anstatt 5, wäre das sehr zu schätzen. Ich konnte keinen Weg finden, das zu tun, weil ich zur Laufzeit Zugriff auf jedes Element in den Merge-Layout-Dateien haben muss …

Benutzer-Avatar
Macarse

Es gibt ein Problem mit dem Include-Tag. Prüfen: https://issuetracker.google.com/issues/36908001

Um das Problem zu beheben, stellen Sie sicher, dass Sie BEIDE überschreiben layout_width und layout_height beim Einbinden, sonst wird alles ignoriert.

  • Dies ist eine bessere Lösung als die akzeptierte, da sie die Erstellung eines ansonsten überflüssigen Layoutobjekts vermeidet. Außerdem ist es scheiße, wie laut den Android-Entwicklern das in Ordnung ist.

    – mikolak

    4. Januar 2012 um 20:20 Uhr

  • Dies ist eine wirklich einfachere, weniger hartcodierte und optimiertere Lösung, als in ein anderes Layout zu packen. Überlegen Sie, was Sie tun würden, wenn Sie mit Listen arbeiten würden.

    – teoREtik

    2. Februar 2012 um 13:31 Uhr

  • Dies funktioniert viel besser als die akzeptierte Antwort. Danke vielmals! Und … komm schon Google, behebe dieses Problem bereits, das ist BS! 🙂

    – Felipe Caldas

    15. August 2012 um 3:15 Uhr

  • @JeffAxelrod , der LayoutInflater-Quellcode zeigt, dass das Überschreiben von id-, Sichtbarkeits- und layout_*-Tags leider nicht angewendet wird, wenn das Stammelement ein Merge-Tag ist. Da Sie keine Ansicht als XML-Root haben können, müssen wir dort eine zusätzliche ViewGroup haben …

    – Raffael Nobre

    24. Juli 2013 um 13:20 Uhr

  • Es hat bei mir einfach nicht funktioniert. ich habe beides layout_width und layout_height setze auf meine <include>. Einstellung habe ich auch probiert layout_width und layout_height auf meinem <merge> aber ohne Erfolg. Was vermisse ich ?

    – dum4ll3

    22. Mai 2014 um 18:21 Uhr


Benutzer-Avatar
Alienjazzcat

Siehe die höher bewertete Antwort unten. Meine ist leider veraltet


Ich kann ein Problem ansprechen Justin ausgelöst: Unfähigkeit von RelativeLayout, die Positionierung eines Include zu verwalten (zumindest in diesem einfachen Fall auf einem 1.6-Emulator)

CommonsWare schlägt vor, die Includes in einen eindeutigen übergeordneten Container zu packen, tut dies jedoch, um das Adressieren und Scoping identisch benannter Views darin zu unterstützen Justins beinhaltet

Jeder müsste einen eindeutigen übergeordneten Container haben, und Sie würden findViewById() für diesen Container (ViewGroup) statt für die Aktivität aufrufen.

Eigentlich du muss es auch machen damit sich RelativeLayout wie erwartet verhält:

Das funktioniert (Fusszeile ist gut aufgestellt):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent">
    <include android:id="@+id/header" layout="@layout/header"
        android:layout_alignParentTop="true" />
    <WebView android:id="@+id/webView" android:layout_below="@id/header"
        android:background="#77CC0000" android:layout_height="wrap_content"
        android:layout_width="fill_parent" android:focusable="false" />
    <LinearLayout android:layout_alignParentBottom="true"
        android:layout_height="wrap_content" android:layout_width="fill_parent">
        <include android:id="@+id/footer" layout="@layout/footer" />
    </LinearLayout>
</RelativeLayout>

Das tut nicht (Fusszeile schwebt oben auf dem Bildschirm):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent">
    <include android:id="@+id/header" layout="@layout/header"
        android:layout_alignParentTop="true" />
    <WebView android:id="@+id/webView" android:layout_below="@id/header"
        android:background="#77CC0000" android:layout_height="wrap_content"
        android:layout_width="fill_parent" android:focusable="false" />
    <include android:id="@+id/footer" layout="@layout/footer"
        android:layout_alignParentBottom="true" />
</RelativeLayout>

Das nackte Fusszeile include wird ohne das umgebende LinearLayout nicht am unteren Rand des übergeordneten Elements ausgerichtet. Ich würde dieses Verhalten nicht als erwartet bezeichnen.

Darüber hinaus scheint sich die WebView gut an die anzuhängen Header per ID, aber ich halte dies für eine Illusion, da es einfach vertikal unter den Header fließt. Ich habe auch versucht, einen Button direkt über dem Footer-Include zu setzen, aber es wurde auch alles schwebend und falsch

RelativeLayout hatte in 1.5 mehr Probleme, aber ich mag es immer noch 🙂

  • Ich habe es um 1 erhöht und dann zurückgenommen, als ich den Kommentar von @Macarse sah, das ist der richtige Weg, es zu tun.

    – Jayshil Dave

    8. März 2013 um 8:38 Uhr

  • Bitte entfernen Sie diese irreführende Antwort 🙁

    – Daniel Schmidt

    25. Februar 2014 um 21:22 Uhr

Mann, das ist alt, aber es scheint ganz oben in der Suche zu stehen, also werde ich es kommentieren.

Ich denke, der Trick hier ist, dass die <merge> Tag kombiniert mit dem <include> Tag entfernt im Wesentlichen jede Art von “übergeordneter” Ansichtsgruppe auf dieser Ebene. Also, wen genau bitten Sie, jemand anderen “layout_below” zu lassen? Niemand. Auf dieser Ebene gibt es keine Aussicht.

Das <merge> -Tag nimmt die untergeordneten Ansichten und fügt sie direkt in die übergeordnete Ansicht von ein <include> Schild. Sie müssen daher die Kinder in der von Ihnen aufgenommenen Anlage bitten, sich entsprechend zu verankern.

Damit die Positionierung auf RelativeLayout funktioniert, müssen Sie die Parameter layout_* in der Include-Datei und nicht in der Hauptlayoutdatei festlegen. Dieser Weg

main_layout.xml

<RelativeLayout
  android:id="@+id/header"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
   ....
</RelativeLayout>

<RelativeLayout 
  android:id="@+id/footer"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true">
    .....
</RelativeLayout>

<include layout="@layout/content_layout" />

content_layout.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
    android:id="@+id/content"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_above="@id/footer"
    android:layout_below="@id/header" >

    ....
</RelativeLayout>
</merge>

Dies ist offensichtlich nicht das, was wir Entwickler wollen, aber es ist die einzige Lösung, die ich gefunden habe, um das Duplizieren von XML zu vermeiden

Die Attribute android:layout_* scheinen ignoriert zu werden, wenn sie im include-Tag verwendet werden, und alle zusammengeführten Layouts werden übereinander angezeigt.

Ich vermute, dass Sie nicht von Layoutregeln referenzieren können, android:id Attribute, die auf definiert sind <include> Elemente, nur solche, die sich auf “echten” Widgets und Containern befinden.

Wenn sich jemand eine Möglichkeit vorstellen kann, nur eine XML-Layoutdatei zusammenzuführen, anstatt 5, wäre das sehr zu schätzen.

Ganz einfach: Legen Sie sie alle in einer Datei ab.

Ich konnte keinen Weg finden, das zu tun, weil ich zur Laufzeit Zugriff auf jedes Element in den Merge-Layout-Dateien haben muss

Ob Sie eine haben <include> element oder 1.000, sollten alle Inhalte zur Laufzeit zugänglich sein. Eine Ausnahme ist, wenn Sie dupliziert haben android:id -Attribute – Sie müssten Ihren Bereich richtig festlegen findViewById() Aufrufe, um das richtige zu erhalten, genau wie beim Abrufen von Widgets aus einer ListView-Zeile.

Wenn Sie ein Beispielprojekt erstellen können, das 2+ Zusammenführungsdateien verwendet, können Sie demonstrieren, dass der Inhalt nicht zur Laufzeit zugänglich, lassen Sie es mich wissen.

  • Ich möchte sie nicht alle in eine riesige Layout-Datei stecken, weil das auf lange Sicht schwieriger zu handhaben ist … Deshalb habe ich um die Möglichkeit gebeten, eine Haupt-XML mit einer Merge-Datei zu haben … weil gerade jetzt Ich habe 5 Dateien mit einem Merge-Element als Root, die genau das gleiche Layout haben, außer dass die IDs unterschiedlich sind. Ich mache das so, dass ich zur Laufzeit darauf zugreifen kann. Es scheint, als würde ich meinen findViewById()-Aufruf einschränken. Wie grenzen Sie diesen Aufruf so ein, dass Sie dieselbe Layoutdatei mehrmals einfügen und dennoch zur Laufzeit auf alle Komponenten zugreifen können?

    – Justin

    23. Februar 2010 um 16:50 Uhr

  • Danke für die Antwort. Ich werde dem nachgehen. In der Zwischenzeit (und vielleicht zeige ich hier meine Unwissenheit) würde das Einpacken jedes Include-Tags in einen übergeordneten Container nicht den Zweck der Verwendung von RelativeLayout zunichte machen? Der ganze Hype um RelativeLayout besteht darin, verschachtelte Layouts zu vermeiden …

    – Justin

    23. Februar 2010 um 23:04 Uhr

  • Der einzige Grund, warum ich danach gefragt habe, war, Platz zu sparen und ein gutes Design zu entwickeln … Ich habe hier über die Wiederverwendbarkeit von Layouts gelesen: developer.android.com/resources/articles/… und fand es klang gut. Als ich versuchte, es zu implementieren, stieß ich auf einige Probleme. Derzeit habe ich 5 Layouts, die im Wesentlichen dupliziert sind, mit Ausnahme der darin enthaltenen IDs … also dachte ich, dass die Wiederverwendbarkeit von Layouts ein guter Kandidat wäre. Vielleicht fehlt mir hier etwas, aber es scheint, als wäre RelativeLayout nicht alles, wofür es angepriesen wird …

    – Justin

    24. Februar 2010 um 0:00 Uhr

  • Wow … danke, dass es so ist unglaublich hilfreich. Im Allgemeinen sind Ihre Antworten ziemlich hilfreich, daher weiß ich nicht, ob Sie nur einen schlechten Tag haben oder was, aber ich habe einfach versucht, ein besseres Verständnis der Konzepte hinter RelativeLayout, dem Include-Tag und dem Merge-Tag zu erlangen, basierend auf Artikel, die ich gelesen habe, und versuche, eine angemessene Lösung für das Layout zu finden, das ich erreichen möchte.

    – Justin

    24. Februar 2010 um 8:07 Uhr

  • “Und für eine echte Wiederverwendung ist das Erstellen einer benutzerdefinierten View-Klasse ein Trumpf” Einverstanden. Ich wollte das einfach nicht tun, wenn es eine relativ einfache Möglichkeit gäbe, grundlegende Layouts zu verwenden … “Sie haben eine Tude erwischt – bitte wundern Sie sich nicht, wenn die Leute darauf reagieren. Und während mein letzter Kommentar ist hoch auf snark, die Punkte sind immer noch gültig” Ich habe ein ‘tude gemacht, weil ich das Gefühl hatte, dass Sie es in Ihren Antworten getan haben. “Der Wechsel zu Zeilen in einer ListView ist möglicherweise besser.” Die Listenansicht funktioniert nicht mit dem Aussehen meiner App. Meine App auf dem Markt ist AppSwipe! wenn du wissen willst was ich mache…

    – Justin

    5. März 2010 um 5:28 Uhr


Benutzer-Avatar
zahra salmaninejad

Versuchen :

<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

  • Ich möchte sie nicht alle in eine riesige Layout-Datei stecken, weil das auf lange Sicht schwieriger zu handhaben ist … Deshalb habe ich um die Möglichkeit gebeten, eine Haupt-XML mit einer Merge-Datei zu haben … weil gerade jetzt Ich habe 5 Dateien mit einem Merge-Element als Root, die genau das gleiche Layout haben, außer dass die IDs unterschiedlich sind. Ich mache das so, dass ich zur Laufzeit darauf zugreifen kann. Es scheint, als würde ich meinen findViewById()-Aufruf einschränken. Wie grenzen Sie diesen Aufruf so ein, dass Sie dieselbe Layoutdatei mehrmals einfügen und dennoch zur Laufzeit auf alle Komponenten zugreifen können?

    – Justin

    23. Februar 2010 um 16:50 Uhr

  • Danke für die Antwort. Ich werde dem nachgehen. In der Zwischenzeit (und vielleicht zeige ich hier meine Unwissenheit) würde das Einpacken jedes Include-Tags in einen übergeordneten Container nicht den Zweck der Verwendung von RelativeLayout zunichte machen? Der ganze Hype um RelativeLayout besteht darin, verschachtelte Layouts zu vermeiden …

    – Justin

    23. Februar 2010 um 23:04 Uhr

  • Der einzige Grund, warum ich danach gefragt habe, war, Platz zu sparen und ein gutes Design zu entwickeln … Ich habe hier über die Wiederverwendbarkeit von Layouts gelesen: developer.android.com/resources/articles/… und fand es klang gut. Als ich versuchte, es zu implementieren, stieß ich auf einige Probleme. Derzeit habe ich 5 Layouts, die im Wesentlichen dupliziert sind, mit Ausnahme der darin enthaltenen IDs … also dachte ich, dass die Wiederverwendbarkeit von Layouts ein guter Kandidat wäre. Vielleicht fehlt mir hier etwas, aber es scheint, als wäre RelativeLayout nicht alles, wofür es angepriesen wird …

    – Justin

    24. Februar 2010 um 0:00 Uhr

  • Wow … danke, dass es so ist unglaublich hilfreich. Im Allgemeinen sind Ihre Antworten ziemlich hilfreich, daher weiß ich nicht, ob Sie nur einen schlechten Tag haben oder was, aber ich habe einfach versucht, ein besseres Verständnis der Konzepte hinter RelativeLayout, dem Include-Tag und dem Merge-Tag zu erlangen, basierend auf Artikel, die ich gelesen habe, und versuche, eine angemessene Lösung für das Layout zu finden, das ich erreichen möchte.

    – Justin

    24. Februar 2010 um 8:07 Uhr

  • “Und für eine echte Wiederverwendung ist das Erstellen einer benutzerdefinierten View-Klasse ein Trumpf” Einverstanden. Ich wollte das einfach nicht tun, wenn es eine relativ einfache Möglichkeit gäbe, grundlegende Layouts zu verwenden … “Sie haben eine Tude erwischt – bitte wundern Sie sich nicht, wenn die Leute darauf reagieren. Und während mein letzter Kommentar ist hoch auf snark, die Punkte sind immer noch gültig” Ich habe ein ‘tude gemacht, weil ich das Gefühl hatte, dass Sie es in Ihren Antworten getan haben. “Der Wechsel zu Zeilen in einer ListView ist möglicherweise besser.” Die Listenansicht funktioniert nicht mit dem Aussehen meiner App. Meine App auf dem Markt ist AppSwipe! wenn du wissen willst was ich mache…

    – Justin

    5. März 2010 um 5:28 Uhr


Benutzer-Avatar
Rohit Mandiwal

In meinem Fall beginnt das Layout, das ich einbinden wollte <merge Schild. Als ich es in ein Layout geändert habe, sagen wir <RelativeLayout es funktionierte. Unten ist die Abbildung.

ARBEITEN

<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

FUNKTIONIERT NICHT

<merge xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

  • Dadurch wird eine weitere verschachtelte Ebene erstellt, die nicht die optimale Lösung ist

    – Silvia H

    15. November 2019 um 9:52 Uhr

1327790cookie-checkWie kann man RelativeLayout mit Merge and Include zum Laufen bringen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy