RecyclerView添加EmptyView(空布局)

作者: 唠嗑008 | 来源:发表于2017-03-13 17:46 被阅读4735次

    github地址(Demo下载)
    https://github.com/zhouxu88/EmptyRecyclerView

    一、简介:

    在项目中用RecyclerView的时候,发现它不可以像以前使用listView或者gridView时,当列表为空时,显示一个特殊的empty view来提示用户。没关系,我们可以自己来实现这个功能。

    三、实现思路

    阅读RecyclerView的源码,可以发现里面自带了一个数据观察者AdapterDataObserver用来监听数据的变化(代码在下面),所以我们自然想到了,自定义一个RecyclerView,重写里面的这个类,然后检查数据源的个数是否为0,当为空的时候,把我们先显示的EmptyView显示出来,这个和以前ListView相似。思路比较简单,直接看看代码是怎么实现的。

    源码中AdapterDataObserver类

    /**
         * Observer base class for watching changes to an {@link Adapter}.
         * See {@link Adapter#registerAdapterDataObserver(AdapterDataObserver)}.
         */
        public static abstract class AdapterDataObserver {
            public void onChanged() {
                // Do nothing
            }
    
            public void onItemRangeChanged(int positionStart, int itemCount) {
                // do nothing
            }
    
            public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
                // fallback to onItemRangeChanged(positionStart, itemCount) if app
                // does not override this method.
                onItemRangeChanged(positionStart, itemCount);
            }
    
            public void onItemRangeInserted(int positionStart, int itemCount) {
                // do nothing
            }
    
            public void onItemRangeRemoved(int positionStart, int itemCount) {
                // do nothing
            }
    
            public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
                // do nothing
            }
        }
    

    四、自定义RecyclerView

    EmptyRecyclerView

    public class EmptyRecyclerView extends RecyclerView {
    
        private View emptyView;
        private static final String TAG = "EmptyRecyclerView";
    
        final private AdapterDataObserver observer = new AdapterDataObserver() {
            @Override
            public void onChanged() {
                checkIfEmpty();
            }
    
            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                Log.i(TAG, "onItemRangeInserted" + itemCount);
                checkIfEmpty();
            }
    
            @Override
            public void onItemRangeRemoved(int positionStart, int itemCount) {
                checkIfEmpty();
            }
        };
    
        public EmptyRecyclerView(Context context) {
            super(context);
        }
    
        public EmptyRecyclerView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public EmptyRecyclerView(Context context, AttributeSet attrs,
                                 int defStyle) {
            super(context, attrs, defStyle);
        }
    
        private void checkIfEmpty() {
            if (emptyView != null && getAdapter() != null) {
                final boolean emptyViewVisible =
                        getAdapter().getItemCount() == 0;
                emptyView.setVisibility(emptyViewVisible ? VISIBLE : GONE);
                setVisibility(emptyViewVisible ? GONE : VISIBLE);
            }
        }
    
        @Override
        public void setAdapter(Adapter adapter) {
            final Adapter oldAdapter = getAdapter();
            if (oldAdapter != null) {
                oldAdapter.unregisterAdapterDataObserver(observer);
            }
            super.setAdapter(adapter);
            if (adapter != null) {
                adapter.registerAdapterDataObserver(observer);
            }
    
            checkIfEmpty();
        }
    
        //设置没有内容时,提示用户的空布局
        public void setEmptyView(View emptyView) {
            this.emptyView = emptyView;
            checkIfEmpty();
        }
    }
    

    重写AdapterDataObserver,每次数据变化都会调用onChanged(),所以就在这里检查数据源是否为空,看一下checkIfEmpty()方法,很简单,就是通过Adapter的getCount来判断时候数据为空,空就显示我们定义的EmptyView。
    最后在setAdapter的时候调用如下代码就可以了。

     mRecyclerView.setEmptyView(mEmptyView); //设置空布局注册
    

    MainActivity:

    public class MainActivity extends AppCompatActivity {
    
        private EmptyRecyclerView mRecyclerView;
        private MyRecycleViewAdapter mAdapter;
        private View mEmptyView;
        private List<ItemData> mList; //数据源
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initData();
            initView();
            initRv();
        }
    
        private void initView() {
            mRecyclerView = (EmptyRecyclerView) findViewById(R.id.emptyRecyclerView);
            mEmptyView = findViewById(R.id.empty_iv);
            findViewById(R.id.deleteAll_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //删除所有数据
                    mList.clear();
                    mAdapter.notifyDataSetChanged();
                }
            });
            findViewById(R.id.insert_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //添加10条数据
                    for (int i = 0; i < 10; i++) {
                        ItemData itemData = new ItemData("列表" + i);
                        mList.add(itemData);
                    }
                    mAdapter.notifyDataSetChanged();
                }
            });
        }
    
        //插入数据
        private void initData() {
            mList = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                ItemData itemData = new ItemData("列表" + i);
                mList.add(itemData);
            }
        }
    
    //初始化RecyclerView    
    private void initRv() {
            mAdapter = new MyRecycleViewAdapter(this, mList);
            mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
            mRecyclerView.setAdapter(mAdapter);
            mRecyclerView.setEmptyView(mEmptyView); //设置空布局,这是关键
        }
    }
    

    布局文件 activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.zmwl.recyclerviewemptyview.MainActivity">
    
        <Button
            android:id="@+id/deleteAll_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="删除所有数据"/>
    
        <Button
            android:id="@+id/insert_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="添加10条数据"
            android:layout_below="@id/deleteAll_btn"/>
    
       <com.zmwl.recyclerviewemptyview.EmptyRecyclerView
           android:id="@+id/emptyRecyclerView"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_below="@id/insert_btn"/>
    
        <!--Empty提示图-->
        <ImageView
            android:id="@+id/empty_iv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:scaleType="centerCrop"
            android:contentDescription="@null"
            android:src="@mipmap/no_data"
            android:layout_centerInParent="true" />
    </RelativeLayout>
    

    相关文章

      网友评论

      • laksg2009:如果加上刷新功能的话RefreshLayout 会无法显示下拉刷新中的圈圈
        唠嗑008:@laksg2009 用这个,http://www.jianshu.com/p/422267f23d01,我的另一篇文章,支持上拉加载更多,下拉刷新,空布局,头布局,尾布局的RecyclerView

      本文标题:RecyclerView添加EmptyView(空布局)

      本文链接:https://www.haomeiwen.com/subject/pqkqnttx.html