我习惯在布局文件中放置一个特殊视图,如ListActivity
没有数据时要显示的文档中所述.此视图具有id "android:id/empty"
.
我想知道如何用新的方式做到这一点RecyclerView
?
在定义的相同布局上RecyclerView
,添加TextView
:
在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); }
对于我的项目,我做了这个解决方案(RecyclerView
使用setEmptyView
方法):
public class RecyclerViewEmptySupport extends RecyclerView { private View emptyView; private AdapterDataObserver emptyObserver = new AdapterDataObserver() { @Override public void onChanged() { Adapter> adapter = getAdapter(); if(adapter != null && emptyView != null) { if(adapter.getItemCount() == 0) { emptyView.setVisibility(View.VISIBLE); RecyclerViewEmptySupport.this.setVisibility(View.GONE); } else { emptyView.setVisibility(View.GONE); RecyclerViewEmptySupport.this.setVisibility(View.VISIBLE); } } } }; public RecyclerViewEmptySupport(Context context) { super(context); } public RecyclerViewEmptySupport(Context context, AttributeSet attrs) { super(context, attrs); } public RecyclerViewEmptySupport(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void setAdapter(Adapter adapter) { super.setAdapter(adapter); if(adapter != null) { adapter.registerAdapterDataObserver(emptyObserver); } emptyObserver.onChanged(); } public void setEmptyView(View emptyView) { this.emptyView = emptyView; } }
你应该使用它而不是RecyclerView
类:
和
RecyclerViewEmptySupport list = (RecyclerViewEmptySupport)rootView.findViewById(R.id.list1); list.setLayoutManager(new LinearLayoutManager(context)); list.setEmptyView(rootView.findViewById(R.id.list_empty));
这是一个解决方案,仅使用具有不同视图类型的自定义适配器来处理空白情况.
public class EventAdapter extends RecyclerView.Adapter{ private static final int VIEW_TYPE_EVENT = 0; private static final int VIEW_TYPE_DATE = 1; private static final int VIEW_TYPE_EMPTY = 2; private ArrayList items; public EventAdapter(ArrayList items) { this.items = items; } @Override public int getItemCount() { if(items.size() == 0){ return 1; }else { return items.size(); } } @Override public int getItemViewType(int position) { if (items.size() == 0) { return VIEW_TYPE_EMPTY; }else{ Object item = items.get(position); if (item instanceof Event) { return VIEW_TYPE_EVENT; } else { return VIEW_TYPE_DATE; } } } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v; ViewHolder vh; if (viewType == VIEW_TYPE_EVENT) { v = LayoutInflater.from(parent.getContext()).inflate( R.layout.item_event, parent, false); vh = new ViewHolderEvent(v); } else if (viewType == VIEW_TYPE_DATE) { v = LayoutInflater.from(parent.getContext()).inflate( R.layout.item_event_date, parent, false); vh = new ViewHolderDate(v); } else { v = LayoutInflater.from(parent.getContext()).inflate( R.layout.item_event_empty, parent, false); vh = new ViewHolder(v); } return vh; } @Override public void onBindViewHolder(EventAdapter.ViewHolder viewHolder, final int position) { int viewType = getItemViewType(position); if (viewType == VIEW_TYPE_EVENT) { //... } else if (viewType == VIEW_TYPE_DATE) { //... } else if (viewType == VIEW_TYPE_EMPTY) { //... } } public static class ViewHolder extends ParentViewHolder { public ViewHolder(View v) { super(v); } } public static class ViewHolderDate extends ViewHolder { public ViewHolderDate(View v) { super(v); } } public static class ViewHolderEvent extends ViewHolder { public ViewHolderEvent(View v) { super(v); } } }
我使用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);
由于凯文的回答并不完整.
这是,如果你使用更加正确的答案RecyclerAdapter
的notifyItemInserted
和notifyItemRemoved
更新的数据集.
只需添加以下代码即可
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); } });
RecyclerView
扩展an AdapterDataObserver
是一种更简单的解决方案,它允许设置View
在列表中没有项目时显示的自定义,而不是使用自定义:
用法示例:
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(); } }
在适配器上getItemViewType
检查适配器是否有0个元素,如果是,则返回不同的viewType.
然后在onCreateViewHolder
检查viewType是否是您之前返回的那个并且膨胀不同的视图.在这种情况下,使用TextView的布局文件
编辑
如果这仍然不起作用,那么您可能希望以编程方式设置视图的大小,如下所示:
Point size = new Point(); ((WindowManager)itemView.getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(size);
然后当你夸大你的观看电话时:
inflatedView.getLayoutParams().height = size.y; inflatedView.getLayoutParams().width = size.x;
这是我的班级,用于显示空视图,重试视图(加载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">... ...
来源在这里https://github.com/PhanVanLinh/AndroidRecyclerViewWithLoadingEmptyAndRetry
在自定义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
在活动中使用这种方式:
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