Android Data Binding usando a tag de inclusão

116

Nota de atualização:

O exemplo acima funciona corretamente , porque a versão 1.0-rc4 corrigiu o problema de precisar da variável desnecessária.

Questão original:

Eu faço exatamente como está descrito na documentação e não funciona:

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'

como obter o botão?

Kamil Nekanowicz
fonte

Respostas:

205

O problema é que o layout incluído não está sendo considerado um layout vinculado a dados. Para fazê-lo agir como um, você precisa passar uma variável:

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

Em seguida, você pode acessar os botões indiretamente por meio do campo de botões:

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

A partir de 1.0-rc4 (recém-lançado), você não precisa mais da variável. Você pode simplificar para:

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
fonte
6
1.0-rc4 agora corrige o problema de precisar da variável desnecessária. Agora você pode usar simplesmente: <include layout="@layout/buttons" android:id="@+id/buttons"/>. Você ainda precisa do id para que ele produza um campo público para você para que possa acessar a Visualização de botões.
George Mount,
1
Alguém mais está tendo problemas para vincular eventos de clique no layout?
Nilzor
5
Ligação de dados com suporte de inclusão. developer.android.com/topic/libraries/data-binding/…
sowmia
1
O ponto principal a lembrar aqui é obter a referência do botão, você precisa fazer em binding.{id of include tag}.buttonvez de binding.button. Levei um tempo para descobrir.
Rishabh876
1
@NeonWarge Há um exemplo completo em developer.android.com/topic/libraries/data-binding/… . Ele adiciona "A vinculação de dados não suporta incluir como filho direto de um elemento de mesclagem"
Ewan
38

Exemplo Completo Fácil

Basta definir o idlayout incluído e usar binding.includedLayout.anyView.

Este exemplo ajuda a passar um valor para <includee acessar as visualizações incluídas no código.

Passo 1

Você tem layout_common.xml, deseja passar Stringpara o layout incluído.

Você criará uma Stringvariável no layout e se referirá Stringa ela TextView.

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

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

Passo 2

Inclua este layout no layout pai. Forneça um idlayout incluído, para que possamos usá-lo na classe de ligação. Agora você pode passar String passedTextpara sua <includetag.

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>
  • Você pode usar agora binding.includedLayout.textViewem sua classe.
  • Você pode passar qualquer variável para o layout incluído como acima.

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

Nota Ambos os layouts (pai e incluídos) devem ser binding layoutembalados com<layout

Khemraj
fonte
Em sua resposta, você manipulou o evento setText programaticamente, em vez de TextView se fosse um Button, então como você lidaria com o evento click. Eu sei que programaticamente binding.includedLayout.button.setOnClickListenerseria a alternativa, mas e se eu quiser usar o onClickatributo em XML em si?
iCantC
Você pode passar OnClickListenerpara o layout incluído. até você pode passar qualquer coisa na ligação. Verifique esta resposta, se precisar de mais ajuda, me avise. stackoverflow.com/a/51722829/6891563
Khemraj
1
Quando faço isso, recebo apenas um campo em branco para passedText. A única diferença é que não incluo o código MainActivity porque só quero passar o recurso de string em <include> e deixá-lo assim. Por que está sempre em branco?
Elliptica
3

Outra coisa interessante nisso é que você pode passar variáveis ​​para o layout importado do fichário assim:

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

Você pode fazer seu bind funcionar em seu include apenas adicionando um ID a ele assim:

<include
            android:id="@+id/loading"
            layout="@layout/loading_layout"
            bind:booleanVisibility="@{viewModel.showLoading}" />
Rodrigo Salomão
fonte
2

apenas defina um id para o seu layout de inclusão

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

então

BUTTONSBINDING binding = yourMainBinding.layout;

BUTTONSBINDING é res / layout / buttons.xml

agora :

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