我习惯于在布局文件中放置一个特殊的视图,如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?
这里是我的类显示空视图,重试视图(当加载api失败时)和加载进度的RecyclerView
public class RecyclerViewEmptyRetryGroup extends RelativeLayout {
private RecyclerView mRecyclerView;
private LinearLayout mEmptyView;
private LinearLayout mRetryView;
private ProgressBar mProgressBar;
private OnRetryClick mOnRetryClick;
public RecyclerViewEmptyRetryGroup(Context context) {
this(context, null);
}
public RecyclerViewEmptyRetryGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RecyclerViewEmptyRetryGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
if (child.getId() == R.id.recyclerView) {
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
return;
}
if (child.getId() == R.id.layout_empty) {
mEmptyView = (LinearLayout) findViewById(R.id.layout_empty);
return;
}
if (child.getId() == R.id.layout_retry) {
mRetryView = (LinearLayout) findViewById(R.id.layout_retry);
mRetryView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mRetryView.setVisibility(View.GONE);
mOnRetryClick.onRetry();
}
});
return;
}
if (child.getId() == R.id.progress_bar) {
mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
}
}
public void loading() {
mRetryView.setVisibility(View.GONE);
mEmptyView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
}
public void empty() {
mEmptyView.setVisibility(View.VISIBLE);
mRetryView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
public void retry() {
mRetryView.setVisibility(View.VISIBLE);
mEmptyView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
public void success() {
mRetryView.setVisibility(View.GONE);
mEmptyView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
public RecyclerView getRecyclerView() {
return mRecyclerView;
}
public void setOnRetryClick(OnRetryClick onRetryClick) {
mOnRetryClick = onRetryClick;
}
public interface OnRetryClick {
void onRetry();
}
}
activity_xml
<...RecyclerViewEmptyRetryGroup
android:id="@+id/recyclerViewEmptyRetryGroup">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"/>
<LinearLayout
android:id="@+id/layout_empty">
...
</LinearLayout>
<LinearLayout
android:id="@+id/layout_retry">
...
</LinearLayout>
<ProgressBar
android:id="@+id/progress_bar"/>
</...RecyclerViewEmptyRetryGroup>
来源在这里https://github.com/PhanVanLinh/AndroidRecyclerViewWithLoadingEmptyAndRetry
这是如何显示空视图,同时过滤和更新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
}
}
我添加了RecyclerView和替代ImageView到RelativeLayout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/no_active_jobs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/ic_active_jobs" />
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
然后在适配器中:
@Override
public int getItemCount() {
if (mOrders.size() == 0) {
mRecyclerView.setVisibility(View.INVISIBLE);
} else {
mRecyclerView.setVisibility(View.VISIBLE);
}
return mOrders.size();
}
RVEmptyObserver
而不是使用自定义的RecyclerView,扩展AdapterDataObserver是一个更简单的解决方案,允许设置一个自定义视图,当列表中没有项目时显示:
使用示例:
RVEmptyObserver observer = new RVEmptyObserver(recyclerView, emptyView)
rvAdapter.registerAdapterDataObserver(observer);
类:
public class RVEmptyObserver extends RecyclerView.AdapterDataObserver {
private View emptyView;
private RecyclerView recyclerView;
public RVEmptyObserver(RecyclerView rv, View ev) {
this.recyclerView = rv;
this.emptyView = ev;
checkIfEmpty();
}
private void checkIfEmpty() {
if (emptyView != null && recyclerView.getAdapter() != null) {
boolean emptyViewVisible = recyclerView.getAdapter().getItemCount() == 0;
emptyView.setVisibility(emptyViewVisible ? View.VISIBLE : View.GONE);
recyclerView.setVisibility(emptyViewVisible ? View.GONE : View.VISIBLE);
}
}
public void onChanged() { checkIfEmpty(); }
public void onItemRangeInserted(int positionStart, int itemCount) { checkIfEmpty(); }
public void onItemRangeRemoved(int positionStart, int itemCount) { checkIfEmpty(); }
}
因为凯文的答案不完整。
如果你使用RecyclerAdapter的notifyItemInserted和notifyItemRemoved来更新数据集,这是更正确的答案。
请参阅下面添加的另一个用户的Kotlin版本。
Java:
mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
checkEmpty();
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
checkEmpty();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
super.onItemRangeRemoved(positionStart, itemCount);
checkEmpty();
}
void checkEmpty() {
mEmptyView.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
});
科特林
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
super.onChanged()
checkEmpty()
}
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
super.onItemRangeInserted(positionStart, itemCount)
checkEmpty()
}
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
super.onItemRangeRemoved(positionStart, itemCount)
checkEmpty()
}
fun checkEmpty() {
empty_view.visibility = (if (adapter.itemCount == 0) View.VISIBLE else View.GONE)
}
})