在数据为空的情况下,列表一般要显示一些提示性的图片以及文字,避免难看的大白屏。iOS下可以使用DZNEmptyDataSet实现这个效果,非常方便。Android下的ListView也可以使用setEmptyView实现,然而Android下的RecyclerView却没有类似的功能,如果要实现这个效果,有以下几个办法。
- 在Context中判断数据是否为空,如果为空,显示空白页,隐藏RecyclerView,如果不为空,显示RecyclerView,隐藏空白页。
- 在Adapter中判断数据是否为空,处理过程同上。
- 重写RecyclerView方法,在数据为空的时,把空白页作为一个Item返回,代码如下
public class CommonRecyclerView extends RecyclerView {
private static final String TAG = "CommonRecyclerView";
private int emptyViewLayout = R.layout.recycler_view_empty_view;
private int imageResourceId = android.R.drawable.ic_menu_add;
private String text;
private EmptyAdapter mEmptyAdapter;
private GridLayoutManager.SpanSizeLookup mSpanSizeLookup;
private Adapter mAdapter;
private GridLayoutManager mGridLayoutManager;
private AdapterDataObserver observer = new AdapterDataObserver() {
public void onChanged() {
mEmptyAdapter.notifyDataSetChanged();
}
public void onItemRangeChanged(int positionStart, int itemCount) {
mEmptyAdapter.notifyItemRangeChanged(positionStart, itemCount);
}
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
onItemRangeChanged(positionStart, itemCount);
}
public void onItemRangeInserted(int positionStart, int itemCount) {
mEmptyAdapter.notifyItemRangeInserted(positionStart, itemCount);
}
public void onItemRangeRemoved(int positionStart, int itemCount) {
mEmptyAdapter.notifyItemRangeRemoved(positionStart, itemCount);
}
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
if (itemCount == 1) {
mEmptyAdapter.notifyItemMoved(fromPosition, toPosition);
} else {
Log.i(TAG, "Not support this");
}
}
};
public CommonRecyclerView(Context context) {
this(context, null, 0);
}
public CommonRecyclerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CommonRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mEmptyAdapter = new EmptyAdapter();
TypedArray array = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.CommonRecyclerView,
0, 0);
imageResourceId = array.getResourceId(R.styleable.CommonRecyclerView_emptyImageSource, android.R.drawable.ic_menu_add);
text = array.getString(R.styleable.CommonRecyclerView_emptyText);
if (text == null || text.length() == 0) {
text = context.getString(R.string.emptyRecyclerView);
}
}
private class EmptyViewHolder extends ViewHolder {
public TextView textView;
public ImageView imageView;
public EmptyViewHolder(View view) {
super(view);
textView = (TextView) view.findViewById(R.id.recycler_view_empty_view_textView);
imageView = (ImageView) view.findViewById(R.id.recycler_view_empty_view_imageView);
}
}
private class EmptyAdapter extends Adapter {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mAdapter.getItemCount() == 0 && viewType == -1) {
View view = LayoutInflater.from(parent.getContext()).inflate(emptyViewLayout, parent, false);
return new EmptyViewHolder(view);
} else {
return mAdapter.onCreateViewHolder(parent, viewType);
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (mAdapter.getItemCount() == 0) {
EmptyViewHolder viewHolder = (EmptyViewHolder) holder;
viewHolder.imageView.setImageResource(imageResourceId);
viewHolder.textView.setText(text);
} else {
mAdapter.onBindViewHolder(holder, position);
}
}
@Override
public int getItemViewType(int position) {
if (mAdapter.getItemCount() == 0) {
return -1;
} else {
return mAdapter.getItemViewType(position);
}
}
@Override
public int getItemCount() {
if (mAdapter.getItemCount() == 0) {
return 1;
} else {
return mAdapter.getItemCount();
}
}
}
@Override
public void setAdapter(Adapter adapter) {
mAdapter = adapter;
super.setAdapter(mEmptyAdapter);
if (mAdapter != null) {
mAdapter.registerAdapterDataObserver(observer);
}
}
@Override
public Adapter getAdapter() {
return mAdapter;
}
@Override
public void setLayoutManager(LayoutManager layoutManager) {
super.setLayoutManager(layoutManager);
if (layoutManager instanceof GridLayoutManager) {
mGridLayoutManager = (GridLayoutManager) layoutManager;
if (mGridLayoutManager.getSpanSizeLookup() != null) {
mSpanSizeLookup = mGridLayoutManager.getSpanSizeLookup();
GridLayoutManager.SpanSizeLookup emptySpanSizeLookup = new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (mAdapter.getItemCount() == 0) {
return mGridLayoutManager.getSpanCount();
} else {
return mSpanSizeLookup.getSpanSize(position);
}
}
};
mGridLayoutManager.setSpanSizeLookup(emptySpanSizeLookup);
}
}
}
}
方法1和方法2的优点在于思路简单,容易操作,缺点时代码比较乱,方法3的优点是代码整洁,使用方便,缺点是代码量多,不容易进行个人化开发。