编辑
给RecyclerView添加空白页功能
本文访问次数:0

在数据为空的情况下,列表一般要显示一些提示性的图片以及文字,避免难看的大白屏。iOS下可以使用DZNEmptyDataSet实现这个效果,非常方便。Android下的ListView也可以使用setEmptyView实现,然而Android下的RecyclerView却没有类似的功能,如果要实现这个效果,有以下几个办法。

  1. 在Context中判断数据是否为空,如果为空,显示空白页,隐藏RecyclerView,如果不为空,显示RecyclerView,隐藏空白页。
  2. 在Adapter中判断数据是否为空,处理过程同上。
  3. 重写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的优点是代码整洁,使用方便,缺点是代码量多,不容易进行个人化开发。

没有任何评论