如何从包含合并标签的布局访问视图包含在另一个布局中?
How can I access views from layout containing merge tag is included in another layout?
我使用 Android Studio 3.6-RC1 和构建工具版本 3.6.0-rc01,遇到 ViewBinding 功能问题:
我有 activity_test.xml 个包含以下标记的文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/view_merged"
layout="@layout/merge_view" />
</LinearLayout>
和 merge_view.xml 具有以下标记:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Merge view" />
</merge>
Activity 代码如下所示:
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityTestBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.viewMerged.label.text = "New text"
}
}
问题是当我尝试从合并布局访问 TextView 时,应用程序抛出异常消息 java.lang.NullPointerException: Missing required view with ID: viewMerged.
生成的绑定 class 如下所示:
public final class ActivityTestBinding implements ViewBinding {
@NonNull
private final LinearLayout rootView;
@NonNull
public final MergeViewBinding viewMerged;
private ActivityTestBinding(@NonNull LinearLayout rootView,
@NonNull MergeViewBinding viewMerged) {
this.rootView = rootView;
this.viewMerged = viewMerged;
}
@Override
@NonNull
public LinearLayout getRoot() {
return rootView;
}
@NonNull
public static ActivityTestBinding inflate(@NonNull LayoutInflater inflater) {
return inflate(inflater, null, false);
}
@NonNull
public static ActivityTestBinding inflate(@NonNull LayoutInflater inflater,
@Nullable ViewGroup parent, boolean attachToParent) {
View root = inflater.inflate(R.layout.activity_test, parent, false);
if (attachToParent) {
parent.addView(root);
}
return bind(root);
}
@NonNull
public static ActivityTestBinding bind(@NonNull View rootView) {
// The body of this method is generated in a way you would not otherwise write.
// This is done to optimize the compiled bytecode for size and performance.
String missingId;
missingId: {
View viewMerged = rootView.findViewById(R.id.view_merged);
if (viewMerged == null) {
missingId = "viewMerged";
break missingId;
}
MergeViewBinding viewMergedBinding = MergeViewBinding.bind(viewMerged);
return new ActivityTestBinding((LinearLayout) rootView, viewMergedBinding);
}
throw new NullPointerException("Missing required view with ID: ".concat(missingId));
}
}
我是不是遗漏了什么,或者无法从带有标签的布局中访问视图,或者它还没有在 Android Studio 3.6-RC1 中发布?
我写了一篇关于使用带有 <merge>
标签的 ViewBinding 的文章,您可以找到 here
基本上,你需要做的是
- 不要给
<include>
标签任何 ID。
- 调用
bind()
生成合并布局绑定的方法,传递包含布局的布局的根视图。
- 从合并绑定的对象访问您的视图
例如,您有 merge_view.xml
,因此您将生成 MergeViewBinding
class,这就是您从此布局访问视图的方式。
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityTestBinding.inflate(layoutInflater)
val mergeBinding = MergeViewBinding.bind(binding.root)
setContentView(binding.root)
mergeBinding.label.text = "New text"
}
}
只需使用view/file的绑定。这是一个例子:
import ch.zkb.mobile.bank.databinding.MyFragmentBinding
import ch.zkb.mobile.bank.databinding.MyMergeBinding
class MyFragment : (R.layout.my_fragment) {
private val binding by viewBinding(MyFragmentBinding::bind)
private val mergeBinding by viewBinding(MyMergeBinding::bind)
...
}
查看示例:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/my_merge" />
</LinearLayout>
确保您首先构建它,以便生成绑定。
我使用 Android Studio 3.6-RC1 和构建工具版本 3.6.0-rc01,遇到 ViewBinding 功能问题:
我有 activity_test.xml 个包含以下标记的文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/view_merged"
layout="@layout/merge_view" />
</LinearLayout>
和 merge_view.xml 具有以下标记:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Merge view" />
</merge>
Activity 代码如下所示:
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityTestBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.viewMerged.label.text = "New text"
}
}
问题是当我尝试从合并布局访问 TextView 时,应用程序抛出异常消息 java.lang.NullPointerException: Missing required view with ID: viewMerged.
生成的绑定 class 如下所示:
public final class ActivityTestBinding implements ViewBinding {
@NonNull
private final LinearLayout rootView;
@NonNull
public final MergeViewBinding viewMerged;
private ActivityTestBinding(@NonNull LinearLayout rootView,
@NonNull MergeViewBinding viewMerged) {
this.rootView = rootView;
this.viewMerged = viewMerged;
}
@Override
@NonNull
public LinearLayout getRoot() {
return rootView;
}
@NonNull
public static ActivityTestBinding inflate(@NonNull LayoutInflater inflater) {
return inflate(inflater, null, false);
}
@NonNull
public static ActivityTestBinding inflate(@NonNull LayoutInflater inflater,
@Nullable ViewGroup parent, boolean attachToParent) {
View root = inflater.inflate(R.layout.activity_test, parent, false);
if (attachToParent) {
parent.addView(root);
}
return bind(root);
}
@NonNull
public static ActivityTestBinding bind(@NonNull View rootView) {
// The body of this method is generated in a way you would not otherwise write.
// This is done to optimize the compiled bytecode for size and performance.
String missingId;
missingId: {
View viewMerged = rootView.findViewById(R.id.view_merged);
if (viewMerged == null) {
missingId = "viewMerged";
break missingId;
}
MergeViewBinding viewMergedBinding = MergeViewBinding.bind(viewMerged);
return new ActivityTestBinding((LinearLayout) rootView, viewMergedBinding);
}
throw new NullPointerException("Missing required view with ID: ".concat(missingId));
}
}
我是不是遗漏了什么,或者无法从带有标签的布局中访问视图,或者它还没有在 Android Studio 3.6-RC1 中发布?
我写了一篇关于使用带有 <merge>
标签的 ViewBinding 的文章,您可以找到 here
基本上,你需要做的是
- 不要给
<include>
标签任何 ID。 - 调用
bind()
生成合并布局绑定的方法,传递包含布局的布局的根视图。 - 从合并绑定的对象访问您的视图
例如,您有 merge_view.xml
,因此您将生成 MergeViewBinding
class,这就是您从此布局访问视图的方式。
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityTestBinding.inflate(layoutInflater)
val mergeBinding = MergeViewBinding.bind(binding.root)
setContentView(binding.root)
mergeBinding.label.text = "New text"
}
}
只需使用view/file的绑定。这是一个例子:
import ch.zkb.mobile.bank.databinding.MyFragmentBinding
import ch.zkb.mobile.bank.databinding.MyMergeBinding
class MyFragment : (R.layout.my_fragment) {
private val binding by viewBinding(MyFragmentBinding::bind)
private val mergeBinding by viewBinding(MyMergeBinding::bind)
...
}
查看示例:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/my_merge" />
</LinearLayout>
确保您首先构建它,以便生成绑定。