web-dev-qa-db-fra.com

Est-ce que Android La disposition XML de la mise en page XML fonctionne vraiment?

Je ne parviens pas à remplacer les attributs lors de l'utilisation de <include> dans mes fichiers de mise en page Android. Lorsque j'ai recherché des bogues, j'ai trouvé Refusé problème 286 :

"La balise include est cassée (la substitution des paramètres de mise en page ne fonctionne jamais)"

Puisque Romain indique que cela fonctionne dans les suites de tests et ses exemples, je dois faire quelque chose de mal.

Mon projet est organisé comme ceci:

res/layout
  buttons.xml

res/layout-land
  receipt.xml

res/layout-port
  receipt.xml

Le buttons.xml contient quelque chose comme ceci:

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

Et les fichiers reçu et portrait portrait.xml ressemblent à:

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

Qu'est-ce que je rate?

84
Eric Burke

Je viens de découvrir le problème. Tout d'abord, vous ne pouvez remplacer que les attributs layout_ *, afin que l'arrière-plan ne fonctionne pas. C'est un comportement documenté et simplement un oubli de ma part.

Le vrai problème se trouve dans 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);
   }
}

Si la balise <include> n'inclut pas both layout_width et layout_height, la RuntimeException se produit et est gérée silencieusement, sans aucune instruction de journal même.

La solution consiste à toujours inclure à la fois layout_width et layout_height lorsque vous utilisez la balise <include>, si vous souhaitez remplacer l'un des attributs layout_ *.

Mon exemple devrait changer en:

<include
      Android:id="@+id/buttons_override"
      Android:layout_width="fill_parent"
      Android:layout_height="wrap_content"
      layout="@layout/buttons"/>
132
Eric Burke

J'ai soumis une demande d'amélioration pour permettre à tous les attributs inclus d'être remplacés:

Supposons que j'ai deux dispositions identiques autres que les valeurs d'un champ TextView. Actuellement, j'ai soit modifier la mise en page au moment de l'exécution ou dupliquer le XML.

Par exemple, pour passer deux paramètres avec les valeurs "bonjour" et "monde" à layout1:

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

layout1a.xml:

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

Une implémentation alternative romprait l'encapsulation et permettrait à l'instruction include de remplacer des valeurs telles que:

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

10
Jeff Axelrod

J'ai constaté que je manquais parfois d'inclure la balise Android: id lors de l'utilisation du générateur d'interface graphique dans Eclipse. S'assurer (quand je le remarque) que j'ajoute dans une TextView du générateur, l'ID que j'utilise dans la mise en page ListView.

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

devient

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

Au lieu de devenir "faux" "faux", je reçois :) et comprend le travail ok.

1
TheSolarSheriff