Liaison de données Android à l'aide de la balise include

116

Note de mise à jour:

L'exemple ci-dessus fonctionne correctement , car la version 1.0-rc4 a résolu le problème du besoin de la variable inutile.

Question originale:

Je fais exactement comme il est décrit dans la documentation et cela ne fonctionne pas:

main.xml:

<layout xmlns:andr...
    <data>
    </data>
       <include layout="@layout/buttons"></include>
....

boutons.xml:

<layout xmlns:andr...>
    <data>
    </data>
    <Button
        android:id="@+id/button"
        ...." />

MyActivity.java:

 ... binding = DataBindingUtil.inflate...
binding.button; ->cannot resolve symbol 'button'

comment obtenir le bouton?

Kamil Nekanowicz
la source

Réponses:

206

Le problème est que la mise en page incluse n'est pas considérée comme une mise en page liée aux données. Pour le faire agir comme un, vous devez passer une variable:

boutons.xml:

<layout xmlns:andr...>
  <data>
    <variable name="foo" type="int"/>
  </data>
  <Button
    android:id="@+id/button"
    ...." />

main.xml:

<layout xmlns:andr...
...
   <include layout="@layout/buttons"
            android:id="@+id/buttons"
            app:foo="@{1}"/>
....

Ensuite, vous pouvez accéder aux boutons indirectement via le champ des boutons:

MainBinding binding = MainBinding.inflate(getLayoutInflater());
binding.buttons.button

Depuis la version 1.0-rc4 (qui vient d'être publiée), vous n'avez plus besoin de la variable. Vous pouvez le simplifier pour:

boutons.xml:

<layout xmlns:andr...>
  <Button
    android:id="@+id/button"
    ...." />

main.xml:

<layout xmlns:andr...
...
   <include layout="@layout/buttons"
            android:id="@+id/buttons"/>
....
George Mount
la source
6
1.0-rc4 corrige maintenant le problème d'avoir besoin de la variable inutile. Vous pouvez maintenant utiliser simplement: <include layout="@layout/buttons" android:id="@+id/buttons"/>. Vous avez toujours besoin de l'identifiant pour qu'il produise un champ public pour vous afin que vous puissiez accéder à la vue des boutons.
George Mount
1
Quelqu'un d'autre a-t-il des problèmes pour lier les événements de clic sur la mise en page?
Nilzor le
5
Liaison de données avec prise en charge de l'inclusion. developer.android.com/topic/libraries/data-binding/…
sowmia
1
Le point principal à retenir ici est d'obtenir la référence du bouton, vous devez le faire à la binding.{id of include tag}.buttonplace de binding.button. Il m'a fallu un certain temps pour le comprendre.
Rishabh876
1
@NeonWarge Il existe un exemple complet sur developer.android.com/topic/libraries/data-binding/… . Il ajoute "La liaison de données ne prend pas en charge l'inclusion en tant qu'enfant direct d'un élément de fusion"
Ewan
38

Exemple complet facile

Juste réglé id en page incluse et utilisez binding.includedLayout.anyView.

Cet exemple permet de transmettre une valeur <includeet d'accéder aux vues incluses dans le code.

Étape 1

Tu as layout_common.xml, tu veux passerString à la mise en page incluse.

Vous créerez Stringvariable dans la mise en page et renvoyer ce Stringà TextView.

<data>
    // declare fields
    <variable
        name="passedText"
        type="String"/>
</data>

<TextView
    android:id="@+id/textView"
    ...
    android:text="@{passedText}"/> //set field to your view.

Étape 2

Incluez cette mise en page dans la mise en page parent. Donnez une idmise en page incluse pour que nous puissions l'utiliser dans la classe de liaison. Vous pouvez maintenant transmettre String passedTextà votre <includebalise.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <LinearLayout
        ..
        >

        <include
            android:id="@+id/includedLayout"
            layout="@layout/layout_common"
            app:passedText="@{@string/app_name}" // here we pass any String 
            />

    </LinearLayout>
</layout>
  • Vous pouvez utiliser maintenant binding.includedLayout.textViewdans votre classe.
  • Vous pouvez transmettre toutes les variables à la mise en page incluse comme ci-dessus.

    ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    binding.includedLayout.textView.setText("text");

Remarque Les deux mises en page (parent et incluses) doivent être binding layoutentourées de<layout

Khemraj
la source
Dans votre réponse, vous avez géré l'événement setText par programme, au lieu de TextView s'il aurait été un bouton, comment auriez-vous géré son événement de clic. Je sais que par programme binding.includedLayout.button.setOnClickListenerserait l'alternative, mais que faire si je veux utiliser l' onClickattribut en XML lui-même?
iCantC
Vous pouvez passer OnClickListenerà la mise en page incluse. même vous pouvez tout passer en liaison. Cochez cette réponse, si vous avez besoin de plus d'aide, faites-le moi savoir. stackoverflow.com/a/51722829/6891563
Khemraj
1
Quand je fais cela, j'obtiens juste un champ vide pour passedText. La seule différence est que je n'inclus pas le code MainActivity parce que je veux juste passer la ressource de chaîne dans <include> et la laisser comme ça. Pourquoi est-il toujours vide?
Elliptica
3

Une autre chose intéressante à ce sujet est que vous pouvez transmettre des variables à la mise en page importée à partir du classeur comme ceci:

MainBinding binding = MainBinding.inflate(getLayoutInflater());
binding.buttons.setVariable(BR.varID, variable)
Cosmin Constantin Firta
la source
3

Vous pouvez faire fonctionner votre liaison sur votre inclusion en y ajoutant simplement un identifiant comme ceci:

<include
            android:id="@+id/loading"
            layout="@layout/loading_layout"
            bind:booleanVisibility="@{viewModel.showLoading}" />
Rodrigo Salomao
la source
2

définissez simplement un identifiant pour votre mise en page d'inclusion

    <include
        android:id="@+id/layout"
        layout="@layout/buttons" />

puis

BUTTONSBINDING binding = yourMainBinding.layout;

BUTTONSBINDING est res / layout / buttons.xml

maintenant :

binding.button.setText("simple_Way");
Sadeq Hitex
la source