我习惯于在布局文件中放置一个特殊的视图,如ListActivity文档中所述,在没有数据时显示。这个视图的id为“android:id/empty”。

<TextView
    android:id="@android:id/empty"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/no_data" />

我想知道这如何能与新的RecyclerView?


当前回答

在自定义RecyclerView中使用AdapterDataObserver

科特林:

RecyclerViewEnum.kt

enum class RecyclerViewEnum {
    LOADING,
    NORMAL,
    EMPTY_STATE
}

RecyclerViewEmptyLoadingSupport.kt

class RecyclerViewEmptyLoadingSupport : RecyclerView {

    var stateView: RecyclerViewEnum? = RecyclerViewEnum.LOADING
        set(value) {
            field = value
            setState()
        }
    var emptyStateView: View? = null
    var loadingStateView: View? = null


    constructor(context: Context) : super(context) {}

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {}


    private val dataObserver = object : AdapterDataObserver() {
        override fun onChanged() {
            onChangeState()
        }

        override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
            super.onItemRangeRemoved(positionStart, itemCount)
            onChangeState()
        }

        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
            super.onItemRangeInserted(positionStart, itemCount)
            onChangeState()
        }
    }


    override fun setAdapter(adapter: RecyclerView.Adapter<*>?) {
        super.setAdapter(adapter)
        adapter?.registerAdapterDataObserver(dataObserver)
        dataObserver.onChanged()
    }


    fun onChangeState() {
        if (adapter?.itemCount == 0) {
            emptyStateView?.visibility = View.VISIBLE
            loadingStateView?.visibility = View.GONE
            this@RecyclerViewEmptyLoadingSupport.visibility = View.GONE
        } else {
            emptyStateView?.visibility = View.GONE
            loadingStateView?.visibility = View.GONE
            this@RecyclerViewEmptyLoadingSupport.visibility = View.VISIBLE
        }
    }

    private fun setState() {

        when (this.stateView) {
            RecyclerViewEnum.LOADING -> {
                loadingStateView?.visibility = View.VISIBLE
                this@RecyclerViewEmptyLoadingSupport.visibility = View.GONE
                emptyStateView?.visibility = View.GONE
            }

            RecyclerViewEnum.NORMAL -> {
                loadingStateView?.visibility = View.GONE
                this@RecyclerViewEmptyLoadingSupport.visibility = View.VISIBLE
                emptyStateView?.visibility = View.GONE
            }
            RecyclerViewEnum.EMPTY_STATE -> {
                loadingStateView?.visibility = View.GONE
                this@RecyclerViewEmptyLoadingSupport.visibility = View.GONE
                emptyStateView?.visibility = View.VISIBLE
            }
        }
    }
}

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/emptyView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/emptyLabelTv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="empty" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/loadingView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:gravity="center"
        android:orientation="vertical">

        <ProgressBar
            android:id="@+id/progressBar"
            android:layout_width="45dp"
            android:layout_height="45dp"
            android:layout_gravity="center"
            android:indeterminate="true"
            android:theme="@style/progressBarBlue" />
    </LinearLayout>

    <com.peeyade.components.recyclerView.RecyclerViewEmptyLoadingSupport
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

在活动中使用这种方式:

recyclerView?.apply {
        layoutManager = GridLayoutManager(context, 2)
        emptyStateView = emptyView
        loadingStateView = loadingView
        adapter = adapterGrid
    }

    // you can set LoadingView or emptyView manual
    recyclerView.stateView = RecyclerViewEnum.EMPTY_STATE
    recyclerView.stateView = RecyclerViewEnum.LOADING

其他回答

另一种方法是使用addOnChildAttachStateChangeListener来处理RecyclerView中出现/消失的子视图。

recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
            @Override
            public void onChildViewAttachedToWindow(@NonNull View view) {
                forEmptyTextView.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onChildViewDetachedFromWindow(@NonNull View view) {
                forEmptyTextView.setVisibility(View.VISIBLE);
            }
        });

我使用ViewSwitcher

<ViewSwitcher
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/switcher"
    >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

    <TextView android:id="@+id/text_empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/list_empty"
        android:gravity="center"
        />

</ViewSwitcher>

在代码中,您将检查光标/数据集和切换视图。

void showItems(Cursor items) {
    if (items.size() > 0) {

        mAdapter.switchCursor(items);

        if (R.id.list == mListSwitcher.getNextView().getId()) {
            mListSwitcher.showNext();
        }
    } else if (R.id.text_empty == mListSwitcher.getNextView().getId()) {
        mListSwitcher.showNext();
    }
}

如果你愿意,你也可以用几行代码设置动画

mListSwitcher.setInAnimation(slide_in_left);
mListSwitcher.setOutAnimation(slide_out_right);

这是如何显示空视图,同时过滤和更新RecyclerView使用LiveData

    ViewModel.getInstance().getCustomers?.observe(viewLifecycleOwner, {customerList ->
           //assign your adapter with your list then
        listAdapter?.notifyDataSetChanged()
        isListItemEmpty(customerList?.isEmpty())
}

创建一个接口来在适配器和片段之间通信,并在适配器中注册它

 interface EmptyListener {
            fun isListEmpty(isEmpty: Boolean)
        }

然后在publishResults中调用它:

        dataList?.isEmpty()?.let { mListener?.isListEmpty(it) }

最后在Fragment中实现你的接口:

 override fun isListEmpty(isEmpty: Boolean) {
        if (isEmpty) {
            your_list?.visibility = View.GONE
            empty_view?.visibility = View.VISIBLE
        } else {
            empty_view?.visibility = View.GONE
            your_list?.visibility = View.VISIBLE
        }
    }

如果你正在使用FirebaseRecyclerAdapter,这篇文章就像一个魅力https://stackoverflow.com/a/39058636/6507009

在定义了RecyclerView的相同布局上,添加TextView:

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />

<TextView
    android:id="@+id/empty_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:visibility="gone"
    android:text="@string/no_data_available" />

在onCreate或适当的回调中,您检查提供RecyclerView的数据集是否为空。 如果数据集为空,那么RecyclerView也是空的。在这种情况下,消息将显示在屏幕上。 如果不是,改变它的可见性:

private RecyclerView recyclerView;
private TextView emptyView;

// ...

recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
emptyView = (TextView) rootView.findViewById(R.id.empty_view);

// ...

if (dataset.isEmpty()) {
    recyclerView.setVisibility(View.GONE);
    emptyView.setVisibility(View.VISIBLE);
}
else {
    recyclerView.setVisibility(View.VISIBLE);
    emptyView.setVisibility(View.GONE);
}