RecyclerView 使用详解

来源:互联网 发布:网络教学的定义 编辑:程序博客网 时间:2024/06/14 14:42

RecycleView是5.0推出的新控件,完美替代ListView,号称艺术般的控件!这篇文章主要介绍如何使用以及它的功能。

  但是完美的东西都不太真实,就像蒙拉丽莎,总要有点缺陷才是最完美的,,大笑,RecycleView中最不完美的就是没有item的点击事件(美中不足),解决办法有两种,下面会说明。


首先需要导包

compile 'com.android.support:appcompat-v7:24.0.0-beta1'compile 'com.android.support:recyclerview-v7:24.0.0'

布局文件中

<android.support.v7.widget.RecyclerView        android:id="@+id/rv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        />



创建RecycleView的Adapter

 class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{      List<String> data;      Context context;     public MyAdapter(List<String> data, Context context) {         this.data = data;         this.context = context;     }      //创建Item的布局     @Override     public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {         View v=View.inflate(context,R.layout.item,null);         return new MyViewHolder(v);     }      //设置数据     @Override     public void onBindViewHolder(MyViewHolder holder, int position) {         holder.tv.setText(data.get(position));     }     //数据总数     @Override     public int getItemCount() {         return data.size();     }             public class MyViewHolder extends RecyclerView.ViewHolder {         TextView tv;         public MyViewHolder(View itemView) {             super(itemView);             tv= (TextView) itemView.findViewById(R.id.tv);         }     } }

需要分类型时的Adapter设置代码片段


  private class HomeChoice extends RecyclerView.Adapter {                       //这里直接继承RecyclerView.Aadapter        private final int ZERO = 0;   //没有图        private final int ONE = 1;    //一张图        private final int THREAD = 3; //三张图        @Override        public int getItemViewType(int position) {                             //返回当前Item的类型            switch (Integer.parseInt(data.get(position).getThumb())) {//根据数据源中的字段判断当前item的类型                case ZERO:                    return ZERO;                case ONE:                    return ONE;                case THREAD:                    return THREAD;            }            return ZERO;        }        @Override        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  //根据类型返回不同的item布局            View v = null;            RecyclerView.ViewHolder hcv = null;            switch (viewType) {                case ZERO:                    v = View.inflate(mContextNews, R.layout.choicenews0, null);                    hcv = new HomeChoiceViewholder_ZERO(v);                    break;                case ONE:                    v = View.inflate(mContextNews, R.layout.choicenews1, null);                    hcv = new HomeChoiceViewholder_ONE(v);                    break;                case THREAD:                    v = View.inflate(mContextNews, R.layout.choicenews3, null);                    hcv = new HomeChoiceViewholder_THREAD(v);                    break;                default:                    v = View.inflate(mContextNews, R.layout.choicenews0, null);                    hcv = new HomeChoiceViewholder_ZERO(v);                    break;            }            return hcv;        }        @Override        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {    //根据返回的类型值分别设置数据            switch (getItemViewType(position)) {                case ZERO:                    final HomeChoiceViewholder_ZERO channel_holder = (HomeChoiceViewholder_ZERO) holder;                    final int[] location = new int[2];                    channel_holder.fast_delete.getLocationOnScreen(location);                    channel_holder.fast_title.setText(data.get(position).getTitle());                    channel_holder.fast_body.setText(data.get(position).getSummary());                    channel_holder.fast_zaixian.setText(data.get(position).getFrom());                    channel_holder.fast_time.setText(data.get(position).getDateline());                    channel_holder.fast_delete.setOnClickListener(new View.OnClickListener() {                        @Override                        public void onClick(View v) {                            pw.setBackgroundDrawable(new BitmapDrawable());                            pw.setOutsideTouchable(true);                            pw.setFocusable(true);                            pw.showAsDropDown(channel_holder.fast_delete, 0, 0);                            WindowManager.LayoutParams attributes1 = window.getAttributes();                            /**背景变暗*/                            attributes1.alpha = 0.7f;                            window.setAttributes(attributes1);                        }                    });                    break;                case ONE:                    final HomeChoiceViewholder_ONE channel_holder_ONE = (HomeChoiceViewholder_ONE) holder;                    channel_holder_ONE.fast_title.setText(data.get(position).getTitle());                    channel_holder_ONE.fast_body.setText(data.get(position).getSummary());                    channel_holder_ONE.fast_zaixian.setText(data.get(position).getFrom());                    channel_holder_ONE.fast_time.setText(data.get(position).getDateline());                    Glide.with(mContextNews).load("http://" + data.get(position).getPic()).placeholder(R.drawable.loading).error(R.drawable.erro).into(channel_holder_ONE.fast_2_);                    channel_holder_ONE.fast_delete.setOnClickListener(new View.OnClickListener() {                        @Override                        public void onClick(View v) {                            pw.setBackgroundDrawable(new BitmapDrawable());                            pw.setOutsideTouchable(true);                            pw.setFocusable(true);                            pw.showAsDropDown(channel_holder_ONE.fast_delete, 0, 0);                            WindowManager.LayoutParams attributes1 = window.getAttributes();                            attributes1.alpha = 0.7f;                            window.setAttributes(attributes1);                        }                    });                    break;                case THREAD:                    HomeChoiceViewholder_THREAD channel_holder_THREAD = (HomeChoiceViewholder_THREAD) holder;                    channel_holder_THREAD.fast_title.setText(data.get(position).getTitle());                    channel_holder_THREAD.fast_zaixian.setText(data.get(position).getFrom());                    channel_holder_THREAD.fast_time.setText(data.get(position).getDateline());                    //Glide.with(mContextNews).load(data.get(position).getPic()).placeholder(R.drawable.bf_icon).into(channel_holder_ONE_THREAD.fast_image1);                    break;            }        }        @Override        public int getItemCount() {            return data.size();        }                                                                                  //创建多个ViewHolder        //ZERO  ViewHolderd        public class HomeChoiceViewholder_ZERO extends RecyclerView.ViewHolder {            private TextView fast_title; //标题            private TextView fast_body;//主体文本            private TextView fast_laiyuan;//来源            private TextView fast_zaixian;//来源地址            private TextView fast_time;//时间            private ImageView fast_delete;//删除            public HomeChoiceViewholder_ZERO(View itemView) {                super(itemView);                fast_title = (TextView) itemView.findViewById(R.id.fast_title);                fast_body = (TextView) itemView.findViewById(R.id.fast_body);                fast_zaixian = (TextView) itemView.findViewById(R.id.fast_zaixian);                fast_time = (TextView) itemView.findViewById(R.id.fast_time);                fast_laiyuan = (TextView) itemView.findViewById(R.id.fast_laiyuan);                fast_delete = (ImageView) itemView.findViewById(R.id.fast_delete);            }        }        //ONE  ViewHolderd        public class HomeChoiceViewholder_ONE extends RecyclerView.ViewHolder {            private TextView fast_title; //标题            private TextView fast_body;//主体文本            private TextView fast_zaixian;//来源            private TextView fast_time;//时间            private ImageView fast_delete;//删除            private ImageView fast_2_;//图片            public HomeChoiceViewholder_ONE(View itemView) {                super(itemView);                fast_title = (TextView) itemView.findViewById(R.id.fast_title);                fast_body = (TextView) itemView.findViewById(R.id.fast_body);                fast_zaixian = (TextView) itemView.findViewById(R.id.fast_zaixian);                fast_time = (TextView) itemView.findViewById(R.id.fast_time);                fast_delete = (ImageView) itemView.findViewById(R.id.fast_delete);                fast_2_ = (ImageView) itemView.findViewById(R.id.fast_2_);            }        }        //THREAD  ViewHolderd        public class HomeChoiceViewholder_THREAD extends RecyclerView.ViewHolder {            private TextView fast_title; //标题            private TextView fast_zaixian;//来源            private TextView fast_time;//时间            private ImageView fast_delete;//删除            private ImageView fast_image1;//图片1            private ImageView fast_image2;//图片3            private ImageView fast_image3;//图片2            public HomeChoiceViewholder_THREAD(View itemView) {                super(itemView);                fast_title = (TextView) itemView.findViewById(R.id.fast_title);                fast_zaixian = (TextView) itemView.findViewById(R.id.fast_zaixian);                fast_time = (TextView) itemView.findViewById(R.id.fast_time);                fast_delete = (ImageView) itemView.findViewById(R.id.fast_delete);                fast_image1 = (ImageView) itemView.findViewById(R.id.fast_image1);                fast_image2 = (ImageView) itemView.findViewById(R.id.fast_image2);                fast_image3 = (ImageView) itemView.findViewById(R.id.fast_image3);            }        }    }

最后设置管理器
和Listview不同的是,添加适配器后还需要设置管理器,就是相当于规定RecyclerView的显示方式,看代码:

(设置完适配器后一定要设置管理器,否则RecyclerView在页面上不会有数据显示)

 RecyclerView rv= (RecyclerView) findViewById(R.id.rv);        setData();//设置数据        rv.setAdapter(new MyAdapter(list,this));        rv.setLayoutManager(new LinearLayoutManager(this, LinearLayout.VERTICAL,false));      //线形        //rv.setLayoutManager(new GridLayoutManager(this,3, GridLayoutManager.HORIZONTAL,false));//网格    }    public void setData(){        list.add("111111");        list.add("222222");        list.add("333333");        list.add("444444");        list.add("555555");        list.add("666666");    }

解释一下两个常用管理器的参数

LinearLayoutManager表示线形显示,其中第三个参数表示是否倒叙

GridLayoutManager表示网格显示,其中第二个参数表示显示几列

另外还有一个StaggeredGridLayoutManager实现爆瀑流效果(就是item的大小不一样),就不做演示了


LinearLayoutManager.VERTICAL

LinearLayoutManager.HORIZONTAL              样式如下:

(HORIZONTAL水平样式是可以滑动的)



GridLayoutManager.VERTICAL

GridLayoutManager.HORIZONTAL          样式如下:




添加item单击事件的两种方法

两种点击事件需要借助一个方法,getLayoutPosition(),表示点击谁,就获得谁的position

第一种:简单粗暴的直接在viewholder中给控件设置OnClickListener

 public class MyViewHolder extends RecyclerView.ViewHolder {        TextView tv;        public MyViewHolder(View itemView) {            super(itemView);            tv = (TextView) itemView.findViewById(R.id.tv);            tv.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    Toast.makeText(context,"点击了"+data.get(getLayoutPosition()),Toast.LENGTH_SHORT).show();                }            });        }    }


第二种:高大上而优雅的方式,添加回调方法,需要自己创建接口,然后添加调用位置,如果之前没有了解过自定义回调的话,第一次可能比较难理解,所以给出完整代码

class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {    List<String> data;    Context context;    MyItemClickListener listener;    public MyAdapter(List<String> data, Context context) {        this.data = data;        this.context = context;    }    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View v = View.inflate(context, R.layout.item, null);        return new MyViewHolder(v);    }    @Override    public void onBindViewHolder(MyViewHolder holder, int position) {        holder.tv.setText(data.get(position));    }    @Override    public int getItemCount() {        return data.size();    }    public class MyViewHolder extends RecyclerView.ViewHolder {        TextView tv;        public MyViewHolder(View itemView) {            super(itemView);            tv = (TextView) itemView.findViewById(R.id.tv);            tv.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    if(listener!=null){//一定要加判断                        listener.myItemClick(v,getLayoutPosition());                    }                }            });        }    }    public void setOnItemClickListener(MyItemClickListener listener) {        this.listener = listener;    }      //创建接口     interface MyItemClickListener {        void myItemClick(View v, int position);    }}
1.思路就是,首先创建一个接口,添加一个让调用者实现的方法

2.然后创建一个公共的方法,参数为创建的接口(让调用者去实现接口中的方法)

3.最后在ViewHolder的控件的onClickLister中调用回调中的方法

需要注意的是第三步需要判断是否为空

下面调用就简单了,用adapter调用自己创建的方法,然后实现接口,看代码

    adapter.setOnItemClickListener(new MyAdapter.MyItemClickListener() {            @Override            public void myItemClick(View v, int position) {                Toast.makeText(MainActivity.this,list.get(position)+"",Toast.LENGTH_SHORT).show();            }        });

 


更新item数据

RecyclerView更新数据的主要API

notifyItemChanged(int position)更新列表position位置上的数据可以调用

notifyItemInserted(int position) 列表position位置添加一条数据时可以调用,伴有动画效果

notifyItemRemoved(int position) 列表position位置移除一条数据时调用,伴有动画效果

notifyItemMoved(int fromPosition, int toPosition) 列表fromPosition位置的数据移到toPosition位置时调用,伴有动画效果

notifyItemRangeChanged(int positionStart, int itemCount)列表从positionStart位置到itemCount数量的列表项进行数据刷新

notifyItemRangeInserted(int positionStart, int itemCount)列表从positionStart位置到itemCount数量的列表项批量添加数据时调用,伴有动画效果notifyItemRangeRemoved(int positionStart, int itemCount) 列表从positionStart位置到itemCount数量的列表项批量删除数据时调用,伴有动画效果

常用的就这三个,添加一条,删除一条,替换所有数据

   public void add(int position,String s){     //添加一条        data.add(position,s);        notifyItemInserted(position);    }    public void del(int position){            //删除一条        data.remove(position);     notifyItemRemoved(position);    }    public void updAll(List<String> s){       //替换集合中所有数据        data.clear();         //清空集合        data.addAll(s);        notifyItemRangeChanged(0,data.size()+s.size());    }

adapter中添加完方法后,外界使用adapter调用相应方法就可以了

    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.add:                adapter.add(3,"ppppppp");                break;            case R.id.del:             adapter.del(3);                break;            case R.id.tihuan:                adapter.updAll(list1);                break;        }    }

效果如下


其他设置

item的动画效果和间隔线,都需要自定义

RecyclerView的item添加动画效果:mRv.setItemAnimator(new DefaultItemAnimator())

RecyclerView的item添加分割线:mRv.addItemDecoration(new ItemDecoration())                      都需要自定义


Recyclerview中的实现标题栏渐变

xrv.addOnScrollListener(new RecyclerView.OnScrollListener() {    @Override    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {        super.onScrollStateChanged(recyclerView, newState);    }    @Override    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {        super.onScrolled(recyclerView, dx, dy);        //滑动的距离        totalDy += dy;        //标题栏的的高度        int bottom = rlBar.getBottom();        //当滑动的距离 <= toolbar高度的时候,改变Toolbar背景色的透明度,达到渐变的效果        if (totalDy <= bottom) {            float scale = (float) totalDy / bottom;            float alpha = scale * 255;            rlBar.setBackgroundColor(Color.argb((int) alpha, 128, 0, 0));        } else {            //上述虽然判断了滑动距离与toolbar高度相等的情况,但是实际测试时发现,标题栏的背景色            //很少能达到完全不透明的情况,所以这里又判断了滑动距离大于toolbar高度的情况,            //将标题栏的颜色设置为完全不透明状态            rlBar.setBackgroundResource(R.color.colorPrimary);        }    }});



然后,RecyclerViw的所有基本用法就说完了,希望能帮到大家大笑





2 0
原创粉丝点击