Wie kann man RelativeLayout mit Merge and Include zum Laufen bringen?
Lesezeit: 14 Minuten
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:
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 …
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
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 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
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…
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
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.