Android Data Binding przy użyciu tagu include

116

Uwaga dotycząca aktualizacji:

Powyższy przykład działa poprawnie , ponieważ poprawiono wydanie 1.0-rc4 problem z potrzebą niepotrzebnej zmiennej.

Oryginalne pytanie:

Robię dokładnie tak, jak jest to opisane w dokumentacji i nie działa:

main.xml:

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

buttons.xml:

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

MyActivity.java:

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

jak zdobyć guzik?

Kamil Nekanowicz
źródło

Odpowiedzi:

206

Problem polega na tym, że dołączony układ nie jest traktowany jako układ powiązany z danymi. Aby działał jak jeden, musisz przekazać zmienną:

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

Następnie możesz uzyskać dostęp do przycisków pośrednio poprzez pole przycisków:

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

Od wersji 1.0-rc4 (właśnie wydanej), nie potrzebujesz już tej zmiennej. Możesz to uprościć, aby:

buttons.xml:

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

main.xml:

<layout xmlns:andr...
...
   <include layout="@layout/buttons"
            android:id="@+id/buttons"/>
....
George Mount
źródło
6
1.0-rc4 rozwiązuje teraz problem wymagający niepotrzebnej zmiennej. Teraz można użyć po prostu: <include layout="@layout/buttons" android:id="@+id/buttons"/>. Nadal potrzebujesz identyfikatora, aby utworzył dla Ciebie pole publiczne, abyś mógł uzyskać dostęp do widoku przycisku.
George Mount
1
Czy ktoś ma jednak problemy z powiązaniem zdarzeń kliknięcia w układzie?
Nilzor
5
Wiązanie danych z obsługą obejmuje. developer.android.com/topic/libraries/data-binding/…
sowmia
1
Najważniejszą rzeczą do zapamiętania jest uzyskanie odniesienia do przycisku, które musisz zrobić binding.{id of include tag}.buttonzamiast binding.button. Zajęło mi trochę czasu, zanim to rozgryzłem.
Rishabh876
1
@NeonWarge Kompletny przykład znajduje się pod adresem developer.android.com/topic/libraries/data-binding/… . Dodaje „Powiązanie danych nie obsługuje uwzględniania jako bezpośredniego elementu podrzędnego elementu scalającego”
Ewan,
38

Prosty kompletny przykład

Wystarczy ustawić iddołączony układ i użyć binding.includedLayout.anyView.

Ten przykład pomaga przekazać wartość do <includei uzyskać dostęp do widoków uwzględnionych w kodzie.

Krok 1

Masz layout_common.xml, chcesz przejść Stringdo zawartego układu.

Utworzysz Stringzmienną w układzie i odniesiesz to Stringdo TextView.

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

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

Krok 2

Dołącz ten układ do układu nadrzędnego. Podaj iddołączony układ, abyśmy mogli go użyć w klasie bindującej. Teraz możesz przekazać String passedTextdo swojego <includetagu.

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>
  • Możesz użyć teraz binding.includedLayout.textView w swojej klasie.
  • Możesz przekazać dowolne zmienne do dołączonego układu, jak powyżej.

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

Uwaga Oba układy (nadrzędny i dołączony) powinny być binding layoutopakowane<layout

Khemraj
źródło
W swojej odpowiedzi obsłużyłeś zdarzenie setText programowo, zamiast TextView, gdyby był to Button, to jak poradziłbyś sobie z jego zdarzeniem kliknięcia Wiem, że programowo binding.includedLayout.button.setOnClickListenerbyłoby to alternatywą, ale co jeśli chcę użyć onClickatrybutu w XML samo ?
iCantC
Możesz przejść OnClickListenerdo dołączonego układu. nawet ty możesz przekazać wszystko w wiązaniu. Sprawdź tę odpowiedź, jeśli potrzebujesz więcej pomocy, daj mi znać. stackoverflow.com/a/51722829/6891563
Khemraj
1
Kiedy to robię, pojawia się puste pole dla passedText. Jedyną różnicą jest to, że nie dołączam kodu MainActivity, ponieważ chcę tylko przekazać zasób ciągu w <include> i tak to zostawić. Dlaczego jest zawsze puste?
Elliptica
3

Inną interesującą rzeczą jest to, że możesz przekazywać zmienne do zaimportowanego układu z segregatora w następujący sposób:

MainBinding binding = MainBinding.inflate(getLayoutInflater());
binding.buttons.setVariable(BR.varID, variable)
Cosmin Constantin Firta
źródło
3

Możesz sprawić, by bind działał na twoim dołączeniu, po prostu dodając do niego identyfikator w następujący sposób:

<include
            android:id="@+id/loading"
            layout="@layout/loading_layout"
            bind:booleanVisibility="@{viewModel.showLoading}" />
Rodrigo Salomao
źródło
2

po prostu ustaw identyfikator dla swojego układu dołączania

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

następnie

BUTTONSBINDING binding = yourMainBinding.layout;

BUTTONSBINDING to res / layout / buttons.xml

teraz :

binding.button.setText("simple_Way");
Sadeq Hitex
źródło