Funktioniert das "Include" -Tag von Android XML Layout wirklich?

84

Ich kann Attribute nicht überschreiben, wenn ich <include> in meinen Android-Layoutdateien verwende. Als ich nach Fehlern suchte, fand ich Declined Issue 2863 :

"include-Tag ist fehlerhaft (das Überschreiben von Layout-Parametern funktioniert nie)"

Da Romain angibt, dass dies in den Testsuiten und seinen Beispielen funktioniert, muss ich etwas falsch machen.

Mein Projekt ist folgendermaßen organisiert:

res/layout
  buttons.xml

res/layout-land
  receipt.xml

res/layout-port
  receipt.xml

Die button.xml enthält ungefähr Folgendes:

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

  <Button .../>

  <Button .../>
</LinearLayout>

Und die Dateien Receipt.xml im Hoch- und Querformat sehen ungefähr so ​​aus:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

  ...

  <!-- Overridden attributes never work. Nor do attributes like
       the red background, which is specified here. -->
  <include
      android:id="@+id/buttons_override"
      android:background="#ff0000"
      android:layout_width="fill_parent"
      layout="@layout/buttons"/>

</LinearLayout>

Was vermisse ich?

Eric Burke
quelle
Auf diese Frage wird von den Android-Entwicklertools verwiesen, wenn Sie versuchen, include auf eine Weise zu verwenden, die nicht unterstützt wird.
ThomasW

Antworten:

132

Ich habe gerade das Problem gefunden. Erstens können Sie nur layout_ * -Attribute überschreiben, sodass der Hintergrund nicht funktioniert. Das ist dokumentiertes Verhalten und einfach ein Versehen meinerseits.

Das eigentliche Problem ist in LayoutInflater.java zu finden:

// We try to load the layout params set in the <include /> tag. If
// they don't exist, we will rely on the layout params set in the
// included XML file.
// During a layoutparams generation, a runtime exception is thrown
// if either layout_width or layout_height is missing. We catch
// this exception and set localParams accordingly: true means we
// successfully loaded layout params from the <include /> tag,
// false means we need to rely on the included layout params.
ViewGroup.LayoutParams params = null;
try {
   params = group.generateLayoutParams(attrs);
} catch (RuntimeException e) {
   params = group.generateLayoutParams(childAttrs);
} finally {
   if (params != null) {
     view.setLayoutParams(params);
   }
}

Wenn das <include> -Tag nicht sowohl layout_width als auch layout_height enthält, tritt die RuntimeException auf und wird unbeaufsichtigt behandelt, auch ohne Protokollanweisung.

Die Lösung besteht darin, bei Verwendung des Tags <include> immer sowohl layout_width als auch layout_height einzuschließen, wenn Sie eines der layout_ * -Attribute überschreiben möchten.

Mein Beispiel sollte sich ändern zu:

<include
      android:id="@+id/buttons_override"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      layout="@layout/buttons"/>
Eric Burke
quelle
33
Das ist lächerlich. Ich habe es nie geschafft, dies zum Laufen zu bringen, und ich habe sogar in der Dokumentation erwähnt, dass sowohl Höhe als auch Breite benötigt werden, wenn versucht wird, Abmessungen zu überschreiben, von denen ich angenommen habe, dass sie Höhe und Breite sind. Ich habe jedoch nur versucht, den Rand zu überschreiben, was eigentlich keine Dimension ist. Warum zum Teufel muss ich beide oder sogar diese angeben, wenn ich nur layout_marginRight ändern möchte? Grrr, Android, manchmal frustrierst du mich zu sehr.
Artem Russakovskii
1
FYI Android Lint gibt Ihnen einen Fehler (Layout-Parameter layout_height wird ignoriert, es sei denn, layout_width ist auch im <include> -Tag angegeben), wenn Sie nicht sowohl die Attribute height als auch width überschreiben
binär
10

Ich habe eine Erweiterungsanforderung eingereicht , damit alle enthaltenen Attribute überschrieben werden können:

Angenommen, ich habe zwei identische Layouts außer den Werten eines TextViewFeldes. Derzeit habe ich entweder das Layout zur Laufzeit geändert oder das XML dupliziert.

Um beispielsweise zwei Parameter mit den Werten "Hallo" und "Welt" an layout1 zu übergeben:

<include layout="@layout/layout1a" params="textView=hello|editText=world" />

layout1a.xml:

<merge><TextView text="@param/textView"><EditText hint="@param/editText"></merge>

Eine alternative Implementierung würde die Kapselung unterbrechen und es der include-Anweisung ermöglichen, Werte wie die folgenden zu überschreiben:

<include layout="@layout/layout1b" overrides="@id/textView.text=hello|@id/editText.hint=world" />

layout1b.xml:

<merge><TextView id="@+id/textView"><EditText hint="@+id/editText"></merge>

Jeff Axelrod
quelle
1
In Anbetracht des neuen Datenbindungsmaterials <include>wird das jetzt noch häufiger verwendet. Das Überschreiben von Daten ist ein Muss
Dmitry Gryazin,
1

Ich habe festgestellt, dass ich manchmal das android: id-Tag vermisse, wenn ich den GUI-Builder in Eclipse verwende. Stellen Sie sicher (wenn ich bemerke), dass ich die vom IDV-Layout verwendete ID in eine TextView aus dem Builder einfüge.

<TextView android:text="@+id/textView1"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" />
...

wird

<TextView android:id="@+id/textView1"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" />
...

Anstatt 'false' 'false' zu bekommen, bekomme ich :) und beinhaltet das Arbeiten in Ordnung.

TheSolarSheriff
quelle