RecycleView的基础使用
2016-04-19 22:17
204 查看
RecycleView
5.0之后的新控件
作用:用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView
使用方式:
控制显示方式
给当前工程添加com.android.support.recyclerview-v7类库
(导入外部library包,
包名为:com.android.support:recyclerview-v7:23.1.0在布局文件中添加要显示的RecyclerView控件,注意:标签名要写RecyclerView的完整路径)
在代码中获取控件对象
设置布局管理器
LinearLayoutManager 线性布局管理器,支持横向,纵向
GridLayoutManager 网格布局管理器
StaggeredGridLayoutManager 瀑布流式布局管理器
此处设置布局管理器的目的在于:由于RecyclerView控件可以实现ListView,GridVIew等多种效果,因此需要通过布局管理器来通知RecyclerView要显示的是ListView效果还是GridView等效果
设置适配器
适配器要使用RecyclerView.Adapter的子类
在适配器的子类中创建RecyclerView类库中的ViewHolder的子类,并将创建适配器子类时设置的泛型设置为当前ViewHolder子类的类型
在ViewHolder子类的构造方法中初始化控件
按要求重写适配器中的方法
nCreateViewHolder:用于初始化ViewHolder子类对象
onBindViewHolder:用于设置ViewHolder子类中控件的显示内容
getItemCount :用于决定RecyclerView中总共要显示多少个条目
控制Item间的间隔线
将路径:sdk\extras\android\support\samples\Support7Demos\src\com\example\android\supportv7\widget\decorator 中的DividerItemDecoration类拷贝到本工程中
通过addItemDecoration方法设置DividerItemDecoration对象即可添加间隔线
如需要自定义间隔线:
在drawable文件夹中通过shape绘制任意形状
在AppTheme样式中添加: <itemname="android:listDivider">@drawable/divider_bg</item>
GridLayoutManager 的用法
通过构造方法初始化对象
通过setLayoutManager方法设置此对象即可
StaggeredGridLayoutManager 的用法
通过构造方法初始化对象
通过setLayoutManager方法设置此对象即可
注:如果要实现瀑布流效果,只需在适配器子类的onBindViewHolder给控件提供随机高度即可
控制点击、长按事件
通过在adapter中添加接口回调手动实现
在onBindViewHolder方法中通过holder.itemView 获取当前item显示的View对象
在监听事件重写方法中通过holder.getLayoutPosition方法获取点击的item所在的position位置
控制Item增删的动画
默认情况下自带动画
或者可以通过setItemAnimator方法设置自定义动画,
也可参考github上的RecyclerViewItemAnimators工程的动画效果
5.0之后的新控件
作用:用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView
可以实现ListView,GridView的效果 可以瀑布流效果 可以方便列表多布局效果 再删除或者增加条目时,支持动画效果 自带View复用效果 |
控制显示方式
给当前工程添加com.android.support.recyclerview-v7类库
(导入外部library包,
包名为:com.android.support:recyclerview-v7:23.1.0在布局文件中添加要显示的RecyclerView控件,注意:标签名要写RecyclerView的完整路径)
在代码中获取控件对象
设置布局管理器
LinearLayoutManager 线性布局管理器,支持横向,纵向
GridLayoutManager 网格布局管理器
StaggeredGridLayoutManager 瀑布流式布局管理器
此处设置布局管理器的目的在于:由于RecyclerView控件可以实现ListView,GridVIew等多种效果,因此需要通过布局管理器来通知RecyclerView要显示的是ListView效果还是GridView等效果
设置适配器
适配器要使用RecyclerView.Adapter的子类
在适配器的子类中创建RecyclerView类库中的ViewHolder的子类,并将创建适配器子类时设置的泛型设置为当前ViewHolder子类的类型
在ViewHolder子类的构造方法中初始化控件
按要求重写适配器中的方法
nCreateViewHolder:用于初始化ViewHolder子类对象
onBindViewHolder:用于设置ViewHolder子类中控件的显示内容
getItemCount :用于决定RecyclerView中总共要显示多少个条目
控制Item间的间隔线
将路径:sdk\extras\android\support\samples\Support7Demos\src\com\example\android\supportv7\widget\decorator 中的DividerItemDecoration类拷贝到本工程中
通过addItemDecoration方法设置DividerItemDecoration对象即可添加间隔线
如需要自定义间隔线:
在drawable文件夹中通过shape绘制任意形状
在AppTheme样式中添加: <itemname="android:listDivider">@drawable/divider_bg</item>
GridLayoutManager 的用法
通过构造方法初始化对象
通过setLayoutManager方法设置此对象即可
StaggeredGridLayoutManager 的用法
通过构造方法初始化对象
通过setLayoutManager方法设置此对象即可
注:如果要实现瀑布流效果,只需在适配器子类的onBindViewHolder给控件提供随机高度即可
控制点击、长按事件
通过在adapter中添加接口回调手动实现
在onBindViewHolder方法中通过holder.itemView 获取当前item显示的View对象
在监听事件重写方法中通过holder.getLayoutPosition方法获取点击的item所在的position位置
控制Item增删的动画
默认情况下自带动画
或者可以通过setItemAnimator方法设置自定义动画,
也可参考github上的RecyclerViewItemAnimators工程的动画效果
适配器创建的步骤: 创建一个RecyclerView.Adapter的子类, 在该子类内部创建一个RecyclerView.ViewHolder的子类,在该类的构造方法中,处理每行的item中的控件的初始化 将适配器子类声明时的泛型修改为第2步中ViewHolder子类类型 重写适配器子类中的方法 /* * 创建Adapter适配器子类, * 泛型的作用: * 限制每行的item要显示的ViewHolder的类型 * */ class MyFirstAdapter extends RecyclerView.Adapter<MyFirstAdapter.MyViewHolder>{ //当初始化MyViewHolder对象时运行 /* * 运行特点为: * 当初始显示时,通过此方法+onBindViewHolder方法控制每一行的显示 * 但是一旦开始滑动,系统判断可以重用时,不再运行此方法, * 只运行onBindViewHolder方法控制显示 * 返回值: * 控制item中控件显示的MyViewHolder对象 * * 参数一:recyclerview对象 * */ @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Log.i("====","====== onCreateViewholder"); return new MyViewHolder(LayoutInflater.from(ReListActivity.this) .inflate(R.layout.item,parent,false)); } //用于填充每一个item中的显示内容 //即设置holder对象中的每一个控件要显示什么样的内容 //参数二:当前的行的position位置 @Override public void onBindViewHolder(MyViewHolder holder, int position) { Log.i("====","====== onBindViewHolder "+position); holder.tv.setText(list.get(position)); } //通过返回值控制列表中总共要显示多少个条目 @Override public int getItemCount() { return list.size(); } /* * 创建一个ViewHolder的子类 * 用于初始化item中控件对象 * */ class MyViewHolder extends RecyclerView.ViewHolder { public TextView tv; public ImageView iv; //参数:列表中显示的item中的View对象 public MyViewHolder(View itemView) { super(itemView); tv = (TextView)itemView.findViewById(R.id.textView); iv = (ImageView)itemView.findViewById(R.id.imageView); } } } 注:RecyclerView的Adapter适配器自带复用效果。 当初始显示时,通过onCreateView方法和onBindViewHolder方法控制item的显示 当可以复用时,直接调用onBindViewHolder复用之前创建的holder对象 简单来说:onCreateView方法用于处理ViewHolder对象的创建,指定item中要显示哪个ViewHolder对象,每个item中显示哪些控件 onBindViewHolder方法 控制的是item中的每个控件上要显示什么样的数据 |
设置RecyclerView的Item的点击事件 RecyclerView中并不存在显示的item点击的监听事件,因此想要获取item的点击事件及获取被点击的item的position时, 添加点击事件的方式为: /* * holder.itemView 代表的是item显示的View对象 * */ holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //如果Adapter是外部类,那么此处的点击事件需要通过接口回调的方式传回给Activity Toast.makeText(ReListActivity.this, "当前被点击的位置为"+holder.getLayoutPosition(), Toast.LENGTH_SHORT).show(); } }); |
实现列表多布局 如实现: * 0-4 显示的是一个TextView * 5-10 显示的是一个ImageView+一个TextView * 11-15 显示的是四个Imageview 关键是针对适配器子类的处理: class MyDuoAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder holder = null ; //根据不同的viewType类型初始化不同的ViewHolder对象 switch (viewType) { case 0: holder = new MyDuoHolder1(LayoutInflater.from(DuoLayoutActivity.this).inflate(R.layout.duo1,parent,false)); break; case 1: holder = new MyDuoHolder2(LayoutInflater.from(DuoLayoutActivity.this).inflate(R.layout.duo2,parent,false)); break; case 2: holder = new MyDuoHolder3(LayoutInflater.from(DuoLayoutActivity.this).inflate(R.layout.duo3,parent,false)); break; } return holder; } //该方法在onCreateViewHolder之后运行,并且接收onCreateViewHolder方法的返回值作为参数1 @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //判断当前返回的holder属性的那种ViewHoder的子类 //根据不同的种类,设置其中控件数据的显示 if (holder instanceof MyDuoHolder1) { MyDuoHolder1 md1 = (MyDuoHolder1) holder; md1.duo1_tv.setText(list.get(position)); } else if (holder instanceof MyDuoHolder2) { MyDuoHolder2 md2 = (MyDuoHolder2) holder; md2.duo2_tv.setText(list.get(position)); //再取出图片数据时注意:要根据当前position-duo1布局中所显示的数据个数才可以 //否则会造成下标越界 md2.duo2_iv.setImageResource(imgs[position-5]); } else if (holder instanceof MyDuoHolder3) { MyDuoHolder3 md3 = (MyDuoHolder3) holder; md3.duo3_iv1.setImageResource(imgs[0]); md3.duo3_iv2.setImageResource(imgs[1]); md3.duo3_iv3.setImageResource(imgs[2]); md3.duo3_iv4.setImageResource(imgs[3]); } } @Override public int getItemCount() { return 16; } //当前的列表布局中有几种不同的分类,那么就在数组中定义n个不重复的数字 int [] type = {0,1,2}; /* * 根据自定义的position判断条件,返回不同的viewType类型 * 该方法优先于onCreateViewHolder方法先运行,并且 * 该方法的返回值会被传递给onCreateViewHolder的参数二 * */ @Override public int getItemViewType(int position) { if (position >=0 && position <=4) { return type[0]; } else if (position >= 5 && position <= 10) { return type[1]; } else { return type[2]; } } //第一种布局对应的holder对象 class MyDuoHolder1 extends RecyclerView.ViewHolder { TextView duo1_tv; public MyDuoHolder1(View itemView) { super(itemView); duo1_tv = (TextView) itemView.findViewById(R.id.textView2); } } //第二种布局对应的holder对象 class MyDuoHolder2 extends RecyclerView.ViewHolder { TextView duo2_tv; ImageView duo2_iv; public MyDuoHolder2(View itemView) { super(itemView); duo2_iv = (ImageView)itemView.findViewById(R.id.imageView2); duo2_tv = (TextView)itemView.findViewById(R.id.textView3); } } //第三种布局对应的holder对象 class MyDuoHolder3 extends RecyclerView.ViewHolder { ImageView duo3_iv1,duo3_iv2,duo3_iv3,duo3_iv4; public MyDuoHolder3(View itemView) { super(itemView); duo3_iv1 = (ImageView)itemView.findViewById(R.id.imageView3); duo3_iv2 = (ImageView)itemView.findViewById(R.id.imageView4); duo3_iv3 = (ImageView)itemView.findViewById(R.id.imageView5); duo3_iv4 = (ImageView)itemView.findViewById(R.id.imageView6); } } } 多布局的运行流程如下: 当getItemCount的返回值不为0时 针对于每一行要显示在屏幕上的item来说,运行流程为: getItemViewType-----onCreateViewHolder(如果可以重用,则不运行此方法)-----OnBindViewHolder |
RecyclerView实现GridView效果: 大体处理方式与实现ListView效果基本一致,只需修改LayoutManager的类型即可 导入外部library包, 包名为:com.android.support:recyclerview-v7:23.1.0 在布局文件中添加要显示的RecyclerView控件,注意:标签名要写RecyclerView的完整路径 在代码中获取控件对象 设置LayoutManager(布局管理器),GridLayoutManager 设置适配器 |
RecyclerView实现瀑布流效果: 处理方式与上方基本一致,不同点为: 将设置的LayoutManger设置为StaggeredGridLayoutManager类型 在适配器中添加构造方法,在构造方法中处理每一个item控件要显示的高度,并通过集合存储起来 在onBindVIew方法中更改holder.item要显示的高度 |
当不想要通过设置margin设置间隔线时: 可通过以下方式进行设置: 控制Item间的间隔线 将路径:sdk\extras\android\support\samples\Support7Demos\src\com\example\android\supportv7\widget\decorator 中的DividerItemDecoration类拷贝到本工程中 通过addItemDecoration方法设置DividerItemDecoration对象即可添加间隔线 如需要自定义间隔线:在drawable文件夹中通过shape绘制任意形状 在AppTheme样式中添加: <item name="android:listDivider">@drawable/divider_bg</item> |
控制Item增删的动画 默认情况下自带动画 或者可以通过setItemAnimator方法设置自定义动画, 自定义的动画效果可参考github上的RecyclerViewItemAnimators工程的动画效果 |
RecyclerViewItemAnimators框架的使用: 先将该框架的library工程导入, 通过Project Structure使RecyclerView所在的工程添加library作为额外库工程,使本工程可以使用library工程中的动画效果类 如果想要实现设置自定义的添加或删除数据的动画: //设置添加或删除数据时的动画效果 rv.setItemAnimator(new SlideInOutLeftItemAnimator(rv)); 新增数据时: list.add(3,"新增的数据"); adapter1.notifyItemInserted(3); 删除数据时: list.remove(3); adapter1.notifyItemRemoved(3); /* * 在参数指定范围内更新数据 * */ adapter1.notifyItemRangeChanged(3,list.size()-1); 如果想要实现让RecyclerView在初始显示时就显示动画: //设置初始显示时的动画效果 adapter1 = new SlideInLeftAnimatorAdapter(new MyFirstAdapter(),rv); //设置适配器 rv.setAdapter(adapter1); |
当设置RecyclerView显示的时候,可以通过 rv.setHasFixSize(true)方法让RecyclerView更高效的进行加载显示 |
相关文章推荐
- 前端笔记 CSS 3
- TransR/CTransR论文:相关工作
- linux同步
- 循环链表双向链表
- C语言文件操作包括static,extern的学习笔记
- POJ 3104-Drying(二分+贪心)
- JDK源码分析之集合02ArrayList
- TabLayout的基础使用
- 经验谈:用 cp 命令复制大量文件(432,000,000个,共39TB)
- ZOJ 3603 Draw Something Cheat (模拟)
- linux下的yum命令详解
- 两点间距离
- PHP中的_FILE_和_DIR_的区别
- Android 计算器
- 最全前端资源汇集
- 粗略浅读计划
- 每日scrum--No.1
- jquery submit()不能提交表单
- javaweb中的request对象
- 牛客网offer直通