数据绑定返回 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 或其他)方法,您仍然可以在其中利用数据绑定您使用自定义选项卡布局,但随后控制手动设置 TabLayoutTab 对象的属性。

希望对您有所帮助!