Werkt de ‘include’-tag van Android XML Layout echt?

Ik kan geen kenmerken overschrijven wanneer ik <include> in mijn Android-layoutbestanden. Toen ik naar bugs zocht, vond ik Afgewezen Issue 2863:

“Include tag is kapot (overschrijven van lay-outparameters werkt nooit)”

Aangezien Romain aangeeft dat dit werkt in de testsuites en zijn voorbeelden, moet ik iets verkeerd doen.

Mijn project is als volgt ingedeeld:

res/layout
  buttons.xml
res/layout-land
  receipt.xml
res/layout-port
  receipt.xml

De buttons.xml bevat zoiets als dit:

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

En de staande en liggende ontvangst.xml-bestanden zien er ongeveer zo uit:

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

Wat mis ik?


Antwoord 1, autoriteit 100%

Ik heb het probleem zojuist gevonden. Ten eerste kunt u alleen layout_*-kenmerken overschrijven, zodat de achtergrond niet werkt. Dat is gedocumenteerd gedrag en gewoon een vergissing van mijn kant.

Het echte probleem wordt gevonden in LayoutInflater.java:

// 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);
   }
}

Als de <include> tag bevat niet zowellayout_width als layout_height, de RuntimeException vindt plaats en wordt stil afgehandeld, zelfs zonder enige log-instructie.

De oplossing is om altijd zowel layout_width als layout_height op te nemen bij gebruik van de <include> tag, als u een van de layout_*-kenmerken wilt overschrijven.

Mijn voorbeeld zou moeten veranderen in:

<include
      android:id="@+id/buttons_override"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      layout="@layout/buttons"/>

Antwoord 2, autoriteit 7%

Ik heb een verbeteringsverzoekingediend om toe te staan ​​dat alle opgenomen kenmerken worden overschreven:

Stel dat ik twee identieke lay-outs heb, behalve de waarden van a
TextViewveld. Momenteel heb ik ofwel de lay-out gewijzigd op
runtime of dupliceer de XML.

Bijvoorbeeld om twee parameters met de waarden “hello” en “world” door te geven aan layout1:

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

layout1a.xml:

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

Een alternatieve implementatie zou de inkapseling verbreken en zou toestaan:
de include-instructie om waarden te overschrijven zoals:

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


Antwoord 3

Ik merkte dat ik soms de tag android:id mis bij het gebruik van de GUI-builder in Eclipse. Ervoor zorgen (wanneer ik merk) dat ik in een TextView van de builder , de id die ik gebruik in de ListView-lay-out toevoeg.

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

wordt

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

In plaats van ‘false’, ‘false’ krijg ik 🙂 en werkt ok.

Other episodes