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的所有基本用法就说完了,希望能帮到大家。
- First RecyclerView (RecyclerView使用详解)
- RecyclerView 的使用详解
- Android RecyclerView 使用详解
- RecyclerView的使用详解
- RecyclerView使用详解
- recyclerview使用详解
- Android RecyclerView使用详解
- Android RecyclerView使用详解
- Android RecyclerView使用详解
- Android RecyclerView使用详解
- RecyclerView 使用详解
- Android RecyclerView使用详解
- RecyclerView框架使用详解
- RecyclerView使用详解(一)
- RecyclerView使用详解(二)
- RecyclerView使用详解(三)
- Android RecyclerView使用详解一
- Android RecyclerView使用详解二
- mvc
- 42:Spark Streaming中checkpoint内幕实现彻底解密
- windows生成GIT SSH发生错误 bash: $'\302\226': command not found
- Android SQLite ORM的框架
- SCSI、FC、iSCSI三大协议概述
- RecyclerView 使用详解
- Java网络编程介绍
- 安卓动画之属性动画(Property Animation)
- mybatis
- this指向 最简单的两种!
- Oauth认证-新浪微博开发(下)
- CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)的内部网络结构区别
- RX操作符之结合操作(startWith、merge、mergeDelayError、zip、join、groupjoin、switchOnNext)
- OpenCV学习笔记(一)——软件配置详述