Android-Datenbindung mit Include-Tag

116

Update-Hinweis:

Das obige Beispiel funktioniert ordnungsgemäß , da Release 1.0-rc4 das Problem behoben hat , dass die unnötige Variable benötigt wird.

Ursprüngliche Frage:

Ich mache genau das, was in der Dokumentation beschrieben ist und es funktioniert nicht:

main.xml:

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

button.xml:

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

MyActivity.java:

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

Wie bekomme ich einen Knopf?

Kamil Nekanowicz
quelle

Antworten:

205

Das Problem ist, dass das enthaltene Layout nicht als datengebundenes Layout betrachtet wird. Damit es als eine Einheit fungiert, müssen Sie eine Variable übergeben:

button.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}"/>
....

Dann können Sie indirekt über das Schaltflächenfeld auf Schaltflächen zugreifen:

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

Ab 1.0-rc4 (gerade veröffentlicht) benötigen Sie die Variable nicht mehr. Sie können es vereinfachen, um:

button.xml:

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

main.xml:

<layout xmlns:andr...
...
   <include layout="@layout/buttons"
            android:id="@+id/buttons"/>
....
George Mount
quelle
6
1.0-rc4 behebt jetzt das Problem, dass die unnötige Variable benötigt wird. Sie können jetzt einfach verwenden : <include layout="@layout/buttons" android:id="@+id/buttons"/>. Sie benötigen die ID weiterhin, damit ein öffentliches Feld für Sie erstellt wird, damit Sie auf die Schaltflächenansicht zugreifen können.
George Mount
1
Hat jemand anderes Probleme beim Binden von Klickereignissen im Layout?
Nilzor
5
Datenbindung mit Include-Unterstützung. developer.android.com/topic/libraries/data-binding/…
sowmia
1
Der wichtigste Punkt, an den Sie sich hier erinnern sollten, ist das Abrufen der Schaltflächenreferenz, die Sie binding.{id of include tag}.buttonanstelle von ausführen müssen binding.button. Ich habe eine Weile gebraucht, um es herauszufinden.
Rishabh876
1
@NeonWarge Ein vollständiges Beispiel finden Sie unter developer.android.com/topic/libraries/data-binding/… . Es fügt hinzu "Datenbindung unterstützt nicht Include als direktes untergeordnetes Element eines Zusammenführungselements"
Ewan
38

Einfaches vollständiges Beispiel

Stellen Sie einfach das identhaltene Layout ein und verwenden Sie es binding.includedLayout.anyView.

In diesem Beispiel können Sie einen Wert an <includeeingeschlossene Ansichten im Code übergeben und auf diese zugreifen.

Schritt 1

Sie haben layout_common.xmlwollen passieren Stringzu enthalten Layout.

Sie erstellen StringVariable im Layout und beziehen sich diese Stringauf TextView.

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

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

Schritt 2

Fügen Sie dieses Layout dem übergeordneten Layout hinzu. Geben Sie ein ideingeschlossenes Layout an, damit wir es in der Bindungsklasse verwenden können. Jetzt können Sie String passedTextan Ihr <includeTag übergeben.

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>
  • Sie können jetzt binding.includedLayout.textViewin Ihrer Klasse verwenden.
  • Sie können beliebige Variablen wie oben beschrieben an das enthaltene Layout übergeben.

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

Hinweis Beide Layouts (übergeordnet und enthalten) sollten mit binding layoutumbrochen werden<layout

Khemraj
quelle
In Ihrer Antwort haben Sie das setText-Ereignis programmgesteuert behandelt. Anstelle von TextView, wenn es eine Schaltfläche gewesen wäre, wie hätten Sie dann das Klickereignis behandelt. Ich weiß, dass programmgesteuert binding.includedLayout.button.setOnClickListenerdie Alternative wäre, aber was ist, wenn ich ein onClickAttribut in XML verwenden möchte selbst?
iCantC
Sie können OnClickListenerzum enthaltenen Layout übergehen . Auch Sie können alles verbindlich übergeben. Überprüfen Sie diese Antwort. Wenn Sie weitere Hilfe benötigen, lassen Sie es mich wissen. stackoverflow.com/a/51722829/6891563
Khemraj
1
Wenn ich das mache, bekomme ich nur ein leeres Feld für passedText. Der einzige Unterschied besteht darin, dass ich den MainActivity-Code nicht einbinde, weil ich nur die Zeichenfolgenressource in <include> übergeben und so belassen möchte. Warum ist es aber immer leer?
Elliptica
3

Eine andere interessante Sache dabei ist, dass Sie Variablen aus dem Ordner wie folgt in das importierte Layout einfügen können:

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

Sie können festlegen, dass Ihre Bindung an Ihrem Include funktioniert, indem Sie einfach eine ID hinzufügen:

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

Legen Sie einfach eine ID für Ihr Include-Layout fest

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

dann

BUTTONSBINDING binding = yourMainBinding.layout;

BUTTONSBINDING ist res / layout / button.xml

jetzt :

binding.button.setText("simple_Way");
Sadeq Hitex
quelle