wake-up-neo.com

Wie kann RelativeLayout mit Merge und Include zusammenarbeiten?

Ich versuche seit einigen Tagen, meine Layouts effizienter zu gestalten, indem ich mehrere verschachtelte LinearLayouts-Ebenen in eine RelativeLayout-Datei konvertiere. Dabei bin ich auf einige Probleme gestoßen, für die ich bisher keine Lösung gefunden habe.

Ich habe die Android-Anfängergruppe und diese Website durchsucht und konnte nichts finden, das mir hilft, das Problem zu lösen.

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 einem RelativeLayout-Wurzelelement. Darin befinden sich fünf Include-Tags, die auf fünf verschiedene XML-Layoutdateien verweisen, die jeweils ein Merge-Element für das Stammverzeichnis enthalten (alle meine Merge-Dateien sind mit Ausnahme der darin enthaltenen IDs identisch). 

Ich habe zwei Probleme, die ich erklären werde, nachdem ich eine vereinfachte Version meines Layoutcodes veröffentlicht habe:

Musterhauptlayoutdatei:

<?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 mitgelieferte Seriendatei:

<?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 habe zwei Probleme:

1) Die Android:layout_*-Attribute werden bei der Verwendung im include-Tag ignoriert und alle zusammengeführten Layouts werden übereinander angezeigt. Gemäß diesem Beitrag ( http://developer.Android.com/resources/articles/layout-tricks-reuse.html ) "kann jedes Android:layout_*-Attribut mit dem <include />-Tag verwendet werden"

2) Da dies nicht funktioniert, habe ich beschlossen, dem ersten TextView-Element in jeder Merge-Layoutdatei ein Android:layout_below-Attribut hinzuzufügen. Dies bedeutet, dass jede Merge-Datei auf eine ID aus einer anderen Merge-Layout-Datei verweist ... Für die meisten Teil funktionierte dies tatsächlich und mein Layout sieht gut aus. Ich erhalte jedoch eine Fehlermeldung in einem der Android:layout_below-Attribute, die besagt, dass die angegebene ID nicht gefunden werden kann. Ich habe die IDs doppelt und dreifach geprüft, um sicherzustellen, dass sie korrekt sind. Der seltsamste Teil ist, dass ich die AutoFill-Funktion verwendet habe, um die ID überhaupt in das Attribut zu setzen.

Wenn jemand Vorschläge oder Problemumgehungen hat, werde ich sie gerne ausprobieren. Wenn sich jemand einen Weg einfallen lässt, nur eine XML-Layoutdatei anstelle von 5 zu erstellen, wäre das sehr zu schätzen. Ich habe keine Möglichkeit dazu gefunden, da ich zur Laufzeit auf jedes Element in den Merge-Layout-Dateien zugreifen muss ...

113
Justin

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

Um das Problem zu beheben, müssen Sie beim Einschließen BOTH layout_width und layout_height überschreiben. Andernfalls wird alles ignoriert.

211
Macarse

Siehe die höher gewählte Antwort unten. Meins ist wahnsinnig veraltet


ich kann mich mit einem Problem befassen Justin Raised: Unfähigkeit von RelativeLayout, die Positionierung eines Include zu verwalten (zumindest in diesem einfachen Fall auf einem Emulator 1.6).

CommonsWare schlägt vor, die Include-Dateien in einen eindeutigen übergeordneten Container zu verpacken, tut dies jedoch, um identifizierbare Views innerhalb von Justin's Includes zu adressieren und zu bestimmen

Jeder müsste eine .__ haben. eindeutiger übergeordneter Container, und Sie würden rufen Sie findViewById () für diesen Container auf (ViewGroup) und nicht auf der Aktivität.

In der Tat müssen Sie muss es auch tun, damit RelativeLayout sich wie erwartet verhält:

Das funktioniert (footer ist gut positioniert):

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

Dies gilt nicht (Fußzeile 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 bloße footer include wird nicht am unteren Rand des übergeordneten Objekts ausgerichtet, ohne das umgebende LinearLayout. Dieses Verhalten würde ich nicht nennen.

Darüber hinaus scheint sich das WebView per ID an den header anzuschließen, aber ich halte das für eine Illusion, da es einfach vertikal unter dem Header fließt. Ich habe auch versucht, einen Button direkt über der Fußzeile zu setzen, aber es wurde alles fließend und falsch

RelativeLayout hatte mehr Probleme in 1.5, aber ich mag es trotzdem :)

32
alienjazzcat

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

Ich denke, der Trick hier ist, dass der <merge>-Tag in Kombination mit dem <include>-Tag im Wesentlichen jegliche "übergeordnete" Ansichtsgruppe auf dieser Ebene entfernt. Also, wen fragen Sie eigentlich, um jemand anderes zu "layout_below"? Niemand. Auf dieser Ebene gibt es keine Sicht.

Mit dem <merge>-Tag werden die untergeordneten Ansichten direkt in das übergeordnete Element des <include>-Tags eingefügt. Sie müssen die Kinder in dem von Ihnen angegebenen Layout daher bitten, sich entsprechend zu verankern.

7
Plantage

Um mit RelativeLayout arbeiten zu können, müssen Sie die Parameter layout_ * in der Include-Datei festlegen, nicht in der Hauptlayoutdatei. 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 habe, um das Duplizieren von XML zu vermeiden

4
Maragues

Die Attribute von Android: layout_ * scheinen Wird bei der Verwendung im Include ignoriert tag und alle zusammengeführten Layouts sind übereinander angezeigt.

Meine Vermutung ist, dass Sie aus Layoutregeln nicht auf Android:id-Attribute verweisen können, die in <include>-Elementen definiert sind, sondern nur auf solche, die sich auf "echten" Widgets und Containern befinden.

Auch wenn sich jemand einen Weg für .__ vorstellen kann. Ich habe nur ein Zusammenführen von XML-Layout Datei statt 5 wäre das sehr geschätzt.

Einfach: Alle in einer Datei ablegen.

Ich konnte keinen Weg finden, das zu tun weil ich Zugang zu jedem .__ haben muss. Element in den Zusammenführungslayoutdateien um Laufzeit

Unabhängig davon, ob Sie ein <include>-Element oder 1.000 haben, sollte der gesamte Inhalt zur Laufzeit verfügbar sein. Eine Ausnahme ist, wenn Sie Android:id-Attribute dupliziert haben - Sie müssten Ihre findViewById()-Aufrufe richtig einschränken, um die richtigen zu erhalten, genau wie Sie es müssen, wenn Sie Widgets aus einer ListView-Zeile abrufen.

Wenn Sie ein Beispielprojekt erstellen können, das 2+ Merge-Dateien verwendet, in denen Sie nachweisen können, dass der Inhalt zur Laufzeit nicht verfügbar ist, lassen Sie es mich wissen.

1
CommonsWare

Ich hatte das gleiche Problem und definierte sogar layout_width und layout_height es funktionierte nicht. Das Problem war, dass das Layout, das ich inklusive Tags hatte, Tags hatte und nachdem ich sie entfernt hatte, alles wie ein Zauber funktionierte Es ist kein Layout-Tag und kann daher keine Positionierungs- und Größenparameter empfangen. Da alles, was Sie definieren, in das innere übergeordnete Layout übertragen wird, wurden die Einstellungen einfach weggeworfen.

TL: DR: Entfernen Sie einfach die Tags, verschieben Sie die xmlns-Definitionen in einen echten Layout-Viewholder, und Sie sollten in Ordnung sein.

Vor:

<merge
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto">

    <...ui.component.BorderCardView
        Android:layout_width="112dp"
        Android:layout_height="32dp"
        app:cardCornerRadius="4dp"
        app:cardUseCompatPadding="true">

        <ImageView
            Android:layout_width="16dp"
            Android:layout_height="16dp"
            Android:src="@drawable/ic_logout"
            Android:tint="@color/divider" />

    </...ui.component.BorderCardView>
</merge>

Arbeiten:

<...ui.component.BorderCardView
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="112dp"
    Android:layout_height="32dp"
    app:cardCornerRadius="4dp"
    app:cardUseCompatPadding="true">

    <ImageView
        Android:layout_width="16dp"
        Android:layout_height="16dp"
        Android:src="@drawable/ic_logout"
        Android:tint="@color/divider" />

</...ui.component.BorderCardView>
0
silvio.pereira

In meinem Fall beginnt das Layout, das ich einschließen wollte, mit dem Tag <merge. Wenn ich es in ein Layout geändert habe, sagen Sie <RelativeLayout, es hat funktioniert. 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">
0
Rohit Mandiwal