RecyclerView学习

从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,是support-v7包中的新组件,是一个强大的滑动组件,拥有item回收复用的功能。
1、基本使用
在使用RecyclerView时候,必须指定一个适配器Adapter和适配器需要的数据源、一个布局管理器LayoutManager。
//设置数据源
List data = initData();
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
//设置布局管理器
rv.setLayoutManager(new LinearLayoutManager(this));
//设置适配器
rv.setAdapter(new NormalAdapter(data));
2、创建适配器
标准实现步骤如下:
① 创建Adapter:创建一个继承RecyclerView.Adapter的Adapter类(VH是ViewHolder的类名)
② 创建ViewHolder:在Adapter中创建一个继承RecyclerView.ViewHolder的静态内部类,记为VH。
③ 在Adapter中实现3个方法:
onCreateViewHolder()
这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。
onBindViewHolder()
这个方法主要用于适配渲染数据到View中,滑动屏幕时,并不是销毁控件,而是修改控件显示的数据,这样效率才高,所以叫RecyclerView。
getItemCount()
这个方法提供总共有多少个条目,RecyclerView对屏幕进行管理,需要知道有多少个条目,这也算是基本要求。
3、基本的Adapter实现

 public class NormalAdapter extends RecyclerView.Adapter{
        public static class VH extends RecyclerView.ViewHolder{
            public final TextView title;
            public VH(View v) {
                super(v);
                title = (TextView) v.findViewById(R.id.title);
            }
        }
        
        private List mDatas;
        public NormalAdapter(List data) {
            this.mDatas = data;
        }
    
        //③ 在Adapter中实现3个方法
        @Override
        public void onBindViewHolder(VH holder, int position) {
            holder.title.setText(mDatas.get(position));
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //item 点击事件
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return mDatas.size();
        }
    
        @Override
        public VH onCreateViewHolder(ViewGroup parent, int viewType) {
            //只有在setContentView()里面的layout中才能使用findViewById(),
            //在运行时inflate加载的布局,不能使用findViewById(),否则会出现空指针异常,必须用View 中的findViewById(int id)
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_1, parent, false);
            return new VH(v);
        }
    }

4、Layout Manager布局管理器
LayoutManager负责RecyclerView的布局,其中包含了Item View的获取与回收,RecyclerView提供了三种布局管理器:
-LinerLayoutManager 以垂直或者水平列表方式展示Item
-GridLayoutManager 以网格方式展示Item
-StaggeredGridLayoutManager 以瀑布流方式展示Item
-LayoutManager 常见 API

    canScrollHorizontally();//能否横向滚动
    canScrollVertically();//能否纵向滚动
    scrollToPosition(int position);//滚动到指定位置
     setOrientation(int orientation);//设置滚动的方向
    getOrientation();//获取滚动方向
    findViewByPosition(int position);//获取指定位置的Item View
    findFirstCompletelyVisibleItemPosition();//获取第一个完全可见的Item位置
    findFirstVisibleItemPosition();//获取第一个可见Item的位置
    findLastCompletelyVisibleItemPosition();//获取最后一个完全可见的Item位置
    findLastVisibleItemPosition();//获取最后一个可见Item的位置

5、Item Decoration间隔样式
RecyclerView通过addItemDecoration()方法添加item之间的分割线。
添加系统分割线recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
自定义间隔样式需要继承RecyclerView.ItemDecoration类,该类是个抽象类,官方目前并没有提供默认的实现类,主要有三个方法。

  • onDraw(Canvas c, RecyclerView parent, State state),在Item绘制之前被调用,该方法主要用于绘制间隔样式。
  • onDrawOver(Canvas c, RecyclerView parent, State state),在Item绘制之前被调用,该方法主要用于绘制间隔样式。
  • getItemOffsets(Rect outRect, View view, RecyclerView parent, State state),设置item的偏移量,偏移的部分用于填充间隔样式,即设置分割线的宽、高;在RecyclerView的onMesure()中会调用该方法。
    onDraw()和onDrawOver()这两个方法都是用于绘制间隔样式,我们只需要复写其中一个方法即可。

public class MyDecoration extends RecyclerView.ItemDecoration{
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
}
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(c, parent, state);
}
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
}
6、Item Animator动画
RecyclerView能够通过mRecyclerView.setItemAnimator(ItemAnimator animator)设置添加、删除、移动、改变的动画效果。
RecyclerView提供了默认的ItemAnimator实现类:DefaultItemAnimator。如果没有特殊的需求,默认使用这个动画即可。
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
7、点击事件
由于 RecyclerView 没有自带的点击事件,因此点击事件必须要由我们自己去设置,我们直接在 MyViewHolder 构造方法中为 选项对象设置点击事件即可:

    public MyViewHolder(View itemView){
                        super(itemView);
                        iv_icon = (ImageView) itemView.findViewById(R.id.iv_icon);
                        tv_title = (TextView) itemView.findViewById(R.id.tv_title);
            
                        //添加点击事件
                        itemView.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(mContext, "当前点击 "+ datas.get(getLayoutPosition()), Toast.LENGTH_SHORT).show();
                                    }
                        });
                      }
许多时候,我们需要在activity中调用点击事件,此时需要我们在适配器里定义接口,然后回调出去即可实现我们的点击事件,在适配器里 创建内部的 接口及 回调方法 。

    //点击 RecyclerView 某条的监听
        public interface OnItemClickListener{
    
            /**
             * 当RecyclerView某个被点击的时候回调
             * @param view 点击item的视图
             * @param data 点击得到的数据
             */
            void onItemClick(View view, String data);
         }
        private OnItemClickListener onItemClickListener;
    
        /**
         * 设置RecyclerView某个的监听
         * @param onItemClickListener
         */
        public void setOnItemClickListener(OnItemClickListener onItemClickListener){
            this.onItemClickListener = onItemClickListener;
        }
        
          public MyViewHolder(View itemView){
                        super(itemView);
                    iv_icon = (ImageView) itemView.findViewById(R.id.iv_icon);
                  tv_title = (TextView) itemView.findViewById(R.id.tv_title);
				itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //Toast.makeText(mContext, "当前点击 "+ datas.get(getLayoutPosition()), Toast.LENGTH_SHORT).show();
                    //调用acitvity的onItemClick
                     if(onItemClickListener != null){
                        onItemClickListener.onItemClick(v, datas.get(getLayoutPosition()));
                    }
                }
            });

在acitivy中生成适配器类对象时,同时生成点击接口匿名类
adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, String data) {
                Toast.makeText(MainActivity.this, "点击-> "+ data, Toast.LENGTH_SHORT).show();
            }
        });

8、局部刷新
RecyclerView提供了notifyItemInserted(),notifyItemRemoved(),notifyItemChanged()等API更新单个或某个范围的Item视图。
除了屏幕内显示的ViewHolder外,屏幕外后台的对列池ViewHolder最多只维持2个,在滑动过程中,只要ViewHolder还没有滑出屏幕就 不需要执行onBindViewHolder和onCreateViewHolder,后台ViewHolder只执行onBindViewHolder,只有在ViewHolder的新建时才执行onCreateViewHolder。

你可能感兴趣的:(RecyclerView学习)