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

118

Примечание к обновлению:

Приведенный выше пример работает правильно , поскольку в выпуске 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'

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

Камил Неканович
источник

Ответы:

207

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

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"/>
....
Джордж Маунт
источник
6
1.0-rc4 теперь решает проблему необходимости в ненужной переменной. Теперь вы можете просто использовать: <include layout="@layout/buttons" android:id="@+id/buttons"/>. Вам по-прежнему нужен идентификатор, чтобы он создавал для вас общедоступное поле, чтобы вы могли получить доступ к представлению кнопок.
Джордж Маунт,
1
Есть ли у кого-нибудь еще проблемы с привязкой событий щелчка к макету?
Nilzor
5
Привязка данных с поддержкой include. developer.android.com/topic/libraries/data-binding/…
sowmia
1
Главное, что нужно помнить здесь, - это получить ссылку на кнопку, которую вам нужно сделать binding.{id of include tag}.buttonвместо binding.button. Мне потребовалось время, чтобы понять это.
Rishabh876
1
@NeonWarge Полный пример можно найти на сайте developer.android.com/topic/libraries/data-binding/… . Он добавляет: «Привязка данных не поддерживает включение в качестве прямого потомка элемента слияния»
Эван
38

Простой полный пример

Просто установите 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включенный макет, чтобы мы могли использовать его в классе привязки. Теперь вы можете передать String 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 = DataBindingUtil.setContentView(this, R.layout.activity_main);
    binding.includedLayout.textView.setText("text");

Примечание. Оба макета (родительский и включенный) должны быть binding layoutобернуты<layout

Khemraj
источник
В своем ответе вы программно обработали событие setText. Вместо TextView, если бы это была кнопка, тогда как бы вы обработали его событие щелчка. Я знаю, что программно это binding.includedLayout.button.setOnClickListenerбыло бы альтернативой, но что, если я хочу использовать onClickатрибут в XML сам ?
iCantC
Вы можете перейти OnClickListenerк включенному макету. даже можно передать что угодно в привязке. Отметьте этот ответ, если вам нужна дополнительная помощь, дайте мне знать. stackoverflow.com/a/51722829/6891563
Хемрадж
1
Когда я это делаю, у меня просто появляется пустое поле passedText. Единственная разница в том, что я не включаю код MainActivity, потому что я просто хочу передать строковый ресурс в <include> и оставить его таким. Но почему он всегда пустой?
Elliptica
3

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

MainBinding binding = MainBinding.inflate(getLayoutInflater());
binding.buttons.setVariable(BR.varID, variable)
Космин Константин Фирта
источник
3

Вы можете заставить свою привязку работать с вашим включением, просто добавив к нему идентификатор, например:

<include
            android:id="@+id/loading"
            layout="@layout/loading_layout"
            bind:booleanVisibility="@{viewModel.showLoading}" />
Родриго Саломао
источник
2

просто установите идентификатор для вашего включаемого макета

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

затем

BUTTONSBINDING binding = yourMainBinding.layout;

BUTTONSBINDING это res / layout / buttons.xml

сейчас :

binding.button.setText("simple_Way");
Садек Хитекс
источник