数据绑定返回 null。正常吗?
Databinding returning null. Is it normal?
我正在使用数据绑定,看起来标签项从数据绑定(但不是 gameTypes)返回 null,这正常吗?其他视图工作正常,因此数据绑定的实现没有问题。这是布局文件的一部分。
<android.support.design.widget.TabLayout
android:id="@+id/gameTypes"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="@android:color/white"
>
<android.support.design.widget.TabItem
android:id="@+id/football"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="football"
android:text="Football"
/>
<android.support.design.widget.TabItem
android:id="@+id/basketball"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="basketball"
android:text="Basketball"/>
</android.support.design.widget.TabLayout>
这是我试图找到所选标签的代码;
private Boolean isSelectedTab(TabItem item, TabLayout.Tab tab) {
if (tab.getTag().equals(item.getTag()))
return true;
return false;
}
错误是;项目为空,即 databinding.basketball
。我认为不应该为空,因为它是 TabItem
.
谢谢。
item is databinding.itemBasketball
不是根据您的代码片段。您的代码片段显示您正在调用 isSelectedTab(b.itemFootballTypes, tab)
。在您的问题中,布局 XML 中没有名为 itemFootballTypes
的任何内容。不过,有一个 itemFootball
选项卡。
您的代码与您的 XML 不一致,所以这可能是一个问题。但是您可能 运行 遇到我们在 TabLayouts
和数据绑定方面遇到的问题。
根本原因似乎是 TabLayout 在 XML 中使用 TabItem
,但它在运行时将其转换为 Tab
。这搞砸了用于创建其引用的内部映射数据绑定。在我们的例子中,我们的 TabItem
实例是从错误的对象中转换而来的。在您的情况下,听起来它可能只是一个空对象。
在任何一种情况下,您似乎都不能可靠地使用 TabLayout
和数据绑定。我们最终创建了一个自定义 View
,它只是包装了一个 TabLayout
,然后通过直接访问它的 Tab
项手动将 "binds" 数据包装到它。
例如,具有 TabLayout
:
的布局
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="viewModel" type="com.app.ViewModel" />
</data>
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@color/white"
app:onTabSelectedListener="@{viewModel.onTabSelectedListener}">
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="@layout/custom_tab_layout">
</android.support.design.widget.TabItem>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="@layout/custom_tab_layout">
</android.support.design.widget.TabItem>
</android.support.design.widget.TabLayout>
然后是包装它的自定义视图:
public class CustomTabLayout extends FrameLayout {
private CustomTabLayoutBinding mBinding;
public CustomTabLayout(@NonNull Context context) {
this(context, null);
}
public CustomTabLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTabLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater inflater = LayoutInflater.from(context);
View tabLayout = inflater.inflate(R.layout.custom_tab_layout, this, false);
addView(tabLayout);
if (!isInEditMode()) {
mBinding = CustomTabLayoutBinding.bind(tabLayout);
}
}
public void setViewModel(@Nullable ViewModel viewModel) {
mBinding.setViewModel(viewModel);
if (viewModel != null) {
updateTabAtIndex(viewModel.getFirstTabViewModel(), 0, viewModel.getSelectedIndex());
updateTabAtIndex(viewModel.getSecondTabViewModel(), 1, viewModel.getSelectedIndex());
}
}
private void updateTabAtIndex(TabViewModel tabViewModel, int index, int selectedIndex) {
TabLayout.Tab tab = mBinding.tabLayout.getTabAt(index);
if (tab == null) {
return;
}
View customView = tab.getCustomView();
if (customView == null) {
return;
}
if (index == selectedIndex) {
tab.select();
}
TextView textView = (TextView) customView.findViewById(R.id.title);
textView.setText(tabViewModel.getTitleText());
TextView subTitleTV = (TextView) customView.findViewById(R.id.subtitle);
subTitleTV.setText(tabViewModel.getSubTitleText());
}
}
然后在您需要 TabLayout 的布局中,改用您的自定义视图:
<com.app.CustomTabLayout
android:id="@+id/custom_tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="@dimen/default_toolbar_elevation"
app:viewModel="@{viewModel.getTabsViewModel}" />
我们在这里使用 MVVM,但希望您能理解要点:通过提供 public setViewModel
(或 setMyData
或其他)方法,您仍然可以在其中利用数据绑定您使用自定义选项卡布局,但随后控制手动设置 TabLayout
中 Tab
对象的属性。
希望对您有所帮助!
我正在使用数据绑定,看起来标签项从数据绑定(但不是 gameTypes)返回 null,这正常吗?其他视图工作正常,因此数据绑定的实现没有问题。这是布局文件的一部分。
<android.support.design.widget.TabLayout
android:id="@+id/gameTypes"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="@android:color/white"
>
<android.support.design.widget.TabItem
android:id="@+id/football"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="football"
android:text="Football"
/>
<android.support.design.widget.TabItem
android:id="@+id/basketball"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="basketball"
android:text="Basketball"/>
</android.support.design.widget.TabLayout>
这是我试图找到所选标签的代码;
private Boolean isSelectedTab(TabItem item, TabLayout.Tab tab) {
if (tab.getTag().equals(item.getTag()))
return true;
return false;
}
错误是;项目为空,即 databinding.basketball
。我认为不应该为空,因为它是 TabItem
.
谢谢。
item is databinding.itemBasketball
不是根据您的代码片段。您的代码片段显示您正在调用 isSelectedTab(b.itemFootballTypes, tab)
。在您的问题中,布局 XML 中没有名为 itemFootballTypes
的任何内容。不过,有一个 itemFootball
选项卡。
您的代码与您的 XML 不一致,所以这可能是一个问题。但是您可能 运行 遇到我们在 TabLayouts
和数据绑定方面遇到的问题。
根本原因似乎是 TabLayout 在 XML 中使用 TabItem
,但它在运行时将其转换为 Tab
。这搞砸了用于创建其引用的内部映射数据绑定。在我们的例子中,我们的 TabItem
实例是从错误的对象中转换而来的。在您的情况下,听起来它可能只是一个空对象。
在任何一种情况下,您似乎都不能可靠地使用 TabLayout
和数据绑定。我们最终创建了一个自定义 View
,它只是包装了一个 TabLayout
,然后通过直接访问它的 Tab
项手动将 "binds" 数据包装到它。
例如,具有 TabLayout
:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="viewModel" type="com.app.ViewModel" />
</data>
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@color/white"
app:onTabSelectedListener="@{viewModel.onTabSelectedListener}">
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="@layout/custom_tab_layout">
</android.support.design.widget.TabItem>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="@layout/custom_tab_layout">
</android.support.design.widget.TabItem>
</android.support.design.widget.TabLayout>
然后是包装它的自定义视图:
public class CustomTabLayout extends FrameLayout {
private CustomTabLayoutBinding mBinding;
public CustomTabLayout(@NonNull Context context) {
this(context, null);
}
public CustomTabLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTabLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater inflater = LayoutInflater.from(context);
View tabLayout = inflater.inflate(R.layout.custom_tab_layout, this, false);
addView(tabLayout);
if (!isInEditMode()) {
mBinding = CustomTabLayoutBinding.bind(tabLayout);
}
}
public void setViewModel(@Nullable ViewModel viewModel) {
mBinding.setViewModel(viewModel);
if (viewModel != null) {
updateTabAtIndex(viewModel.getFirstTabViewModel(), 0, viewModel.getSelectedIndex());
updateTabAtIndex(viewModel.getSecondTabViewModel(), 1, viewModel.getSelectedIndex());
}
}
private void updateTabAtIndex(TabViewModel tabViewModel, int index, int selectedIndex) {
TabLayout.Tab tab = mBinding.tabLayout.getTabAt(index);
if (tab == null) {
return;
}
View customView = tab.getCustomView();
if (customView == null) {
return;
}
if (index == selectedIndex) {
tab.select();
}
TextView textView = (TextView) customView.findViewById(R.id.title);
textView.setText(tabViewModel.getTitleText());
TextView subTitleTV = (TextView) customView.findViewById(R.id.subtitle);
subTitleTV.setText(tabViewModel.getSubTitleText());
}
}
然后在您需要 TabLayout 的布局中,改用您的自定义视图:
<com.app.CustomTabLayout
android:id="@+id/custom_tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="@dimen/default_toolbar_elevation"
app:viewModel="@{viewModel.getTabsViewModel}" />
我们在这里使用 MVVM,但希望您能理解要点:通过提供 public setViewModel
(或 setMyData
或其他)方法,您仍然可以在其中利用数据绑定您使用自定义选项卡布局,但随后控制手动设置 TabLayout
中 Tab
对象的属性。
希望对您有所帮助!