Android 使用 include 标签进行数据绑定
Android Data Binding using include tag
更新说明:
上面的例子工作正常,因为1.0-rc4版本修复了需要不必要变量的问题。
原问题:
我完全按照 documentation 中的描述进行操作,但它不起作用:
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'
如何获取按钮?
问题是包含的布局未被视为数据绑定布局。要让它作为一个,你需要传递一个变量:
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"/>
....
另一件有趣的事情是,您可以像这样将变量传递给从活页夹导入的布局:
MainBinding binding = MainBinding.inflate(getLayoutInflater());
binding.buttons.setVariable(BR.varID, variable)
简单完整的例子
Just set id
to included layout, and use 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
,以便我们可以在绑定 class 中使用它。现在您可以将 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>
- 您现在可以在 class 中使用
binding.includedLayout.textView
。
您可以像上面那样将任何变量传递给包含的布局。
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.includedLayout.textView.setText("text");
注意 两种布局(父布局和包含布局)都应 binding layout
,用 <layout
包裹
您可以让您的绑定在您的包含上工作,只需向它添加一个 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>
如果您不使用,请删除此标签,将解决问题
我想补充一下,我遇到了类似的问题。
我的问题是变量名是 title,与 id 名称相同。
没有编译错误。 (不是 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>
只要确保您的包含布局启用了 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 { 完成() }
binding.back.tvBack.text = getText(R.string.video_call)
更新说明:
上面的例子工作正常,因为1.0-rc4版本修复了需要不必要变量的问题。
原问题:
我完全按照 documentation 中的描述进行操作,但它不起作用:
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'
如何获取按钮?
问题是包含的布局未被视为数据绑定布局。要让它作为一个,你需要传递一个变量:
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"/>
....
另一件有趣的事情是,您可以像这样将变量传递给从活页夹导入的布局:
MainBinding binding = MainBinding.inflate(getLayoutInflater());
binding.buttons.setVariable(BR.varID, variable)
简单完整的例子
Just set
id
to included layout, and usebinding.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
,以便我们可以在绑定 class 中使用它。现在您可以将 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>
- 您现在可以在 class 中使用
binding.includedLayout.textView
。 您可以像上面那样将任何变量传递给包含的布局。
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.includedLayout.textView.setText("text");
注意 两种布局(父布局和包含布局)都应 binding layout
,用 <layout
您可以让您的绑定在您的包含上工作,只需向它添加一个 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>
如果您不使用,请删除此标签,将解决问题
我想补充一下,我遇到了类似的问题。 我的问题是变量名是 title,与 id 名称相同。 没有编译错误。 (不是 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>
只要确保您的包含布局启用了 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 { 完成() }
binding.back.tvBack.text = getText(R.string.video_call)