使用 include 标记的 Android 数据绑定

更新注释:

上面的例子 正常运作,因为版本1.0-rc4 修好了需要不必要的变量的问题。

原问题:

我完全按照 文件中描述的那样做,但它不起作用:

Xml:

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

Xml:

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

返回文章页面 MyActivity.java:

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

如何得到按钮?

102040 次浏览

问题是所包含的布局没有被认为是数据绑定布局。为了使其作为一个变量,需要传递一个变量:

Xml:

<layout xmlns:andr...>
<data>
<variable name="foo" type="int"/>
</data>
<Button
android:id="@+id/button"
... />

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(刚刚发布)开始,您就不再需要这个变量了,您可以将它简化为:

Xml:

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

Xml:

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

另一个有趣的事情是,您不能像下面这样从活页夹中导入布局的变量:

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

简单完整例子

只需将 id设置为包含布局,并使用 binding.includedLayout.anyView

此示例帮助向 <include传递值并访问代码中包含的视图。

第一步

你有 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.

第二步

将此布局包括到父布局。给包含的布局一个 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 = DataBindingUtil.setContentView(this, R.layout.activity_main);
    binding.includedLayout.textView.setText("text");
    

Note Both layouts (parent & included) should be binding layout, wrapped with <layout

您可以使绑定工作在您的 include 上,只需向其添加一个 ID,如下所示:

<include
android:id="@+id/loading"
layout="@layout/loading_layout"
bind:booleanVisibility="@{viewModel.showLoading}" />

只需为您的包含布局设置一个 id 即可

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

那么

BUTTONSBINDING binding = yourMainBinding.layout;

BUTTONSBINDING是 res/layout/buttons.xml

现在:

binding.button.setText("simple_Way");

似乎您有空的数据标签在您的 xml 文件请交叉检查,这是使原因不生成包含布局文件

 <data>


</data>

删除此标签,如果你不使用,将解决问题

我想补充的是,我也有过类似的问题。 我的问题是变量 name 是 title,与 id name 相同。 没有编译错误。(不是100% 肯定这是一个问题,我也清理项目)

<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>


<variable
name="title"
type="String" />
</data>
...
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/title"...>
<androidx.appcompat.widget.AppCompatTextView>
...
</layout>

只需确保 include 布局已启用 dataBinding 标记

下面的代码是我的布局,我包括在其他布局

<data>


<variable
name="backBinding"
type="String" />


</data>


<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cl_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen_30"
android:layout_marginTop="@dimen/dimen_30"
android:padding="@dimen/dimen_2"
app:layout_constraintStart_toStartOf="parent">


<ImageView
android:id="@+id/iv_back"
android:layout_width="@dimen/dimen_10"
android:layout_height="@dimen/dimen_20"
android:contentDescription="@string/back"
android:src="@drawable/ic_back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />


<TextView
android:id="@+id/tv_back"
style="@style/AidoFTTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen_10"
android:text="@string/face_training"
android:textSize="@dimen/text_20"
app:layout_constraintBottom_toBottomOf="@id/iv_back"
app:layout_constraintStart_toEndOf="@id/iv_back"
app:layout_constraintTop_toTopOf="@id/iv_back" />


</androidx.constraintlayout.widget.ConstraintLayout>

在这里,我包括在我的主要布局

<data>


<variable
name="viewModel"
type="com.ingenDynamic.coreaidokotlin.viewModels.VideoCallViewModel" />


</data>


<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/aido_main_background"
tools:context=".ui.aidoVideoCall.ContactActivity">


<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/back_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen_20"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_appBar">


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


</androidx.constraintlayout.widget.ConstraintLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

我可以直接访问我的内置布局

binding.backLayout.setOnClickListener { finish() }
binding.back.tvBack.text = getText(R.string.video_call)