Привязка данных Android с использованием тега include

Обновление заметки:

Приведенный выше пример работает правильно, потому что в выпуске 1.0-rc4 устранена проблема с необходимостью использования ненужной переменной.

Оригинальный вопрос:

Я делаю именно так, как описано в документации, и это не работает:

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'

как получить кнопку?

Ответ 1

Проблема в том, что включенный макет не рассматривается как макет с привязкой к данным. Чтобы заставить его действовать как единое целое, вам нужно передать переменную:

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

Затем вы можете получить доступ к кнопкам косвенно через поле кнопок:

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

Начиная с 1.0-rc4 (только что выпущен), вам больше не нужна переменная. Вы можете упростить это до:

buttons.xml:

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

main.xml:

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

Ответ 2

Легко завершенный пример

Просто установите id для включенного макета и используйте binding.includedLayout.anyView.

Этот пример помогает передать значение <include и получить доступ к включенным представлениям в коде.

Шаг 1

У вас есть layout_common.xml, вы хотите передать String во включенный макет.

Вы создадите String переменную в макете и передадите эту String в TextView.

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

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

Шаг 2

Включить этот макет в родительский макет. Присвойте id включенному макету, чтобы мы могли использовать его в классе привязки. Теперь вы можете передать passedText в ваш тег <include.

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>
  • Теперь вы можете использовать binding.includedLayout.textView в вашем классе.
  • Вы можете передавать любые переменные во включенный макет, как указано выше.

    ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater()); binding.includedLayout.textView.setText("text");

Note-, что оба макета (родительский и включенный) должны быть binding layout, завернутым в <layout

Ответ 3

Еще одна интересная вещь в том, что вы можете использовать переменные pas для импортированного макета из этого связующего:

MainBinding binding = MainBinding.inflate(getLayoutInflater());
binding.buttons.setVariable(BR.varID, variable)