Прив’язка даних Android за допомогою тегу include


116

Оновлення примітки:

Наведений вище приклад працює належним чином , оскільки випуск 1.0-rc4 виправив проблему необхідності непотрібної змінної.

Оригінальне запитання:

Я роблю точно так, як це описано в документації, і це не працює:

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'

як отримати кнопку?

Відповіді:


206

Проблема полягає в тому, що включений макет не розглядається як макет, пов'язаний з даними. Щоб змусити його діяти як єдине ціле, вам потрібно передати змінну:

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

Потім ви можете отримати доступ до кнопок опосередковано через поле кнопок:

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

Станом на 1.0-rc4 (щойно випущений), вам більше не потрібна змінна. Ви можете спростити його до:

button.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
Обв'язування даних з підтримкою. developer.android.com/topic/libraries/data-binding/…
sowmia

1
Головне, що слід пам’ятати тут, - це отримати посилання на кнопку, що потрібно зробити binding.{id of include tag}.buttonзамість binding.button. Зайняв мене час, щоб зрозуміти це.
Ришабх876

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


У своїй відповіді ви обробляли подію setText програмно, а не TextView, якби це була кнопка, то як би ви обробляли її подія клацання. Я знаю, що програмно binding.includedLayout.button.setOnClickListenerбуло б альтернативою, але що робити, якщо я хочу використовувати onClickатрибут у XML себе?
iCantC

Ви можете перейти OnClickListenerдо включеного макета. навіть ви можете передати що завгодно в обов'язковому порядку. Перевірте цю відповідь, якщо вам потрібна додаткова допомога, дайте мені знати. stackoverflow.com/a/51722829/6891563
Khemraj

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 / button.xml

зараз:

binding.button.setText("simple_Way");
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.