当前位置:网站首页>RecycleView的一些使用
RecycleView的一些使用
2022-07-01 05:21:00 【初级炼丹师Yiky--1229】
依赖
在项目的gradle文件中引入一下这个包
implementation 'androidx.recyclerview:recyclerview:1.2.0'
基本使用
Activity
中代码
//首先要找到该组件(必做)
RecyclerView recyclerView = findViewById(R.id.recycleView);
//准备要展示的数据源(必做)
photoBeanList =PhotoUtil.getPhotosFromFiles(MainActivity.this);
//设置LayoutManager(必做),这里设置网格布局
//设置 layoutManager 这个是Recycleview必须的 不然Recycleview 的内容不会显示。
//RecyclView提供了 LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager 3 个系统的。当然也可以继承LayoutManager自定义
recyclerView.setLayoutManager(newGridLayoutManager(MainActivity.this, 3));
//下面是线性 layoutManager的用法,后面还会详细介绍
//LinearLayoutManager layoutManager = new //LinearLayoutManager(this);
//如果将 orientation 设置为 HORIZONTAL 可以轻易的实现横向的 listview 效果 //layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
//recyclerView.setLayoutManager(layoutManager);
//创建适配器对象(必做)
adapter = new PhotoAdapter(MainActivity.this, photoBeanList);
//设置适配器(必做)
recyclerView.setAdapter(adapter);
//设置动画(可选,在增加或删除条目时的动画)
recyclerView.setItemAnimator(new DefaultItemAnimator());
//使用自带的分割线
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL));
//自定义分割(可选,需要继承RecyclerView.ItemDecoration类)
recyclerView.addItemDecoration(new mydivider());
Adapter
对应代码
基本的步骤为:
为
RecyclerView
新增适配器PhotoAdapter
,并让其继承于RecyclerView.Adapter
,把泛型指定为PhotoAdapter .ViewHolder
。
定义内部类ViewHolder,并继承RecyclerView.ViewHolder。传入的View参数通常是RecyclerView子项的最外层布局。PhotoAdapter
构造函数,用于把要展示的数据源传入,并赋予值给全局变量dataList
。PhotoAdapter
继承RecyclerView.Adapter
。因为必须重写onCreateViewHolder()
,onBindViewHolder()
和getItemCount()
三个方法
onCreateViewHolder()
用于创建ViewHolder
实例,并把加载的布局传入到构造函数去,再把ViewHolder
实例返回。onBindViewHolder()
则是用于对子项的数据进行赋值,会在每个子项被滚动到屏幕内时执行。position
得到当前项的photo
实例。getItemCount()
返回RecyclerView
的子项数目。
/** * @ClassName PhotoAdapter * @Description 图片数据适配器 * @Author Yu * @Date 2022/6/17 10:53 * @Version 1.0 **/
//此处 继承的 RecyclerView.Adapter 中的泛型指定为我们自定义的 ViewHolder的类型(static class ViewHolder extends RecyclerView.ViewHolder)
public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.ViewHolder>{
private List<PhotoBean> dataList;
private BaseActivity activity;
private PhotoBean bean;
private int selectedIndex=-1;//用于记录当前选中的索引
public void setSelectedIndex(int position) {
this.selectedIndex = position;
}
public PhotoAdapter (BaseActivity activity,List<PhotoBean> dataList){
this.dataList=dataList;
this.activity=activity;
}
/** 创建 viewHolder 将 xml 传递给ViewHolder */
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.photo_item, parent, false);
ViewHolder holder = new ViewHolder(view);
holder.item_photo.setOnLongClickListener(v->{
int position = holder.getAdapterPosition();
setSelectedIndex(position);//声明并赋值一个当前选中的索引
AlertDialog.Builder builder = new AlertDialog.Builder(activity);//dialog
builder.setTitle("温馨提示");
builder.setMessage("真的要删除吗?删除后不可恢复");
builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
//确定对应的回执事件
@Override
public void onClick(DialogInterface dialog, int which) {
int i = PhotoUtil.deleteFromFile(activity, dataList.get(selectedIndex).getpId());//从数据库中删除
if (i>0){
Toast.makeText(activity, "删除成功!", Toast.LENGTH_SHORT).show();
dataList.remove(selectedIndex);//从列表中删除
notifyItemRemoved(selectedIndex);
//refreshList(dataList);//刷新视图
}else{
Toast.makeText(activity, "删除失败!", Toast.LENGTH_SHORT).show();
}
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.create().show();
return true;
});
return holder;
}
/** 这里是设置item操作的地方 */
@Override
public void onBindViewHolder(@NonNull PhotoAdapter.ViewHolder holder, int position) {
bean=dataList.get(position);
Glide.with(activity)
.load(bean.getUrl())
.error(R.drawable.picloaderror)
.centerCrop()
.into(holder.item_photo);
holder.item_photo.setOnClickListener(v->{
//点击任意一张图片对应事件
Intent intent = new Intent(activity, PhotoViewPagesActivity.class);
intent.putParcelableArrayListExtra("DATALIST",(ArrayList<PhotoBean>) dataList);//传递数据
intent.putExtra("CURRENTPOSITION",position);
activity.overridePendingTransition(R.anim.scale_in, R.anim.scale_out);
activity.startActivity(intent);
});
}
/** 跟 BaseAdapter 的 getCount 作用一样。返回 */
@Override
public int getItemCount() {
return dataList == null ? 0 : dataList.size();
}
/** ViewHolder类,这个类用来初始化控件 */
static class ViewHolder extends RecyclerView.ViewHolder {
private ImageView item_photo;
ViewHolder(@NonNull View itemView) {
super(itemView);
item_photo=itemView.findViewById(R.id.iv_photo_item);
}
}
}
LayoutManager 布局管理器
LayoutManager
用于指定RecyclerView的布局方式。系统也为我们提供了三个实现类,同时提供了一个可供用户自定义布局管理抽象类RecycleView.LayoutManager
类
LinearLayoutManager
:线性布局, 支持纵向、横向(可以很轻松的实现横向listview的效果)
mRecyclerView.layoutManager = LinearLayoutManager(context上下文,显示方向,是否反转显示)
GridLayoutManager
:网格布局,线性布局是单行显示,网格布局可以设置并行显示的列数(竖直方向显示)
mRecyclerView.layoutManager = GridLayoutManager(上下文,显示行(列)数,显示方向,是否逆转显示)
StaggeredGridLayoutManage
:瀑布布局,类似淘宝商品展示的效果,可以交错显示
mRecyclerView.layoutManager = StaggeredGridLayoutManager(显示行(列)数,显示方向)
ItemDecoration 分割线
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
recycleView
提供了一个分割线类。 VERTICAL
表示分割线在item的底部,如果改为HORIZONTAL
则分割线在item的右侧。这个Decoration
类还可以设置 setDrawable()
要实现更加酷炫的分割线效果需要继承ItemDecoratio
类 进行自定义。ItemDecoratio
类 中包含以下三个方法:
onDraw()
方法在drawChildren之前调用onDrawOver()
方法在drawChildren之后调用getItemOffsets()
方法中可以利用outRect为每个item设置一定的偏移量以实现给RecycleView的item添加边距
onDraw
和onDrawOver
方法针对的是RecycleView
本身。所以,在这两个方法中要遍历屏幕上可见的item,分别计算和绘制分割线。绘制完成后onDraw在item下面,item在中间,onDrawOver是可以盖住onDraw和item的
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(c, parent, state);
// 这个方法得到的 RecycleView 中 child view 的个数,也就是屏幕中显示的item的个数。并不是adapter中数据源的大小
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i ++) {
View child = parent.getChildAt(i);
int left = child.getLeft() + mDividerW / 2;
int right = child.getRight() + 60;
int top = child.getBottom() - mDividerW;
int bottom = child.getBottom() + mDividerW / 2;
c.drawRect(left, top, right, bottom, paint);
c.drawText("onDraw", (right)/2, bottom - 40, paintText);
}
}
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i ++) {
View child = parent.getChildAt(i);
int left = child.getLeft() + mDividerW / 2;
int right = child.getRight() + 60;
int top = child.getTop() - mDividerW / 2;
int bottom = child.getTop() + mDividerW / 2;
c.drawRect(left, top, right, bottom, paintOver);
c.drawText("onDrawOver", (right)/2, bottom - 40, paintText);
}
}
getItemOffsets
方法针对的是每一个item
//这里我们设置item(left,top,right,bottom)四周的间隔分别为(20, 20, 0, 20)
outRect.set(20, 20, 0, 20);
当我们设置了recyclerView.addItemDecoration(官方分割线类/自定义类)
后,当recycleView
绘制的时候,会绘制我们设置的 Decoration。
ItemAnimator 动画
为RecycleView
设置动画,只要调用recyclerView.setItemAnimator(new DefaultItemAnimator());
方法即可,这也是一个抽象类,我们可以继承这个类自定义动画,同时系统也为我们提供了一个默认动画DefaultItemAnimator。
这里要注意呈现ItemAnimator
需要调用RecycleView.Adapter
中notifyItemRemoved(position)/notifyItemInserted();/notifyItemChanged
等方法,调用notifyDataSetChanged()
方法动画是无效的。
注意事项:实际增删操作过程中position不会自动增加,导致数据错位的问题,所以,当我们需要使用这些特效方法的时候,必须要重新刷新一遍数据,纠正position。或者用viewHolder.getAdapterPosition()获取我们需要的position进行数据操作
notifyDataSetChanged()
;列表全局刷新,给recyleview添加增删条目的动画时,调用这种刷新方法时无法生效的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数量的列表项批量删除数据时调用,伴有动画效果
RecycleView的优化策略
- 不要在onBindViewHolder中设置监听器,在onCreateViewHolder中设置监听器
- 使用DiffUtilRecyclerView.setHasFixedSize()方法
- 使用 LinearLayoutManager.setInitialPrefetchitemCount()方法
- 多个RectclerView共用RecycledViewPool.
边栏推荐
- 轻松上手Fluentd,结合 Rainbond 插件市场,日志收集更快捷
- Rust hello-word
- What can the points mall Games bring to businesses? How to build a points mall?
- Things generated by busybox
- How to hide browser network IP address and modify IP internet access?
- Tcp/ip explanation (version 2) notes / 3 link layer / 3.2 Ethernet and IEEE 802 lan/man standards
- 工业导电滑环的应用
- 第05天-文件操作函数
- Unity项目心得总结
- Variable binding and deconstruction for rudimentary rust
猜你喜欢
Distributed - summary list
eBPF Cilium实战(2) - 底层网络可观测性
LevelDB源码分析之memtable
Redis数据库的部署及常用命令
TypeORM 框架
Summary of spanner's paper
Unity drags and modifies scene camera parameters under the editor
Using nocalhost to develop microservice application on rainbow
Practice of combining rook CEPH and rainbow, a cloud native storage solution
每日一题-LeetCode1175-质数排列-数学
随机推荐
Application of industrial conductive slip ring
使用 Nocalhost 开发 Rainbond 上的微服务应用
[data recovery in North Asia] a data recovery case of raid crash caused by hard disk drop during data synchronization of hot spare disk of RAID5 disk array
Use of STM32 expansion board temperature sensor and temperature humidity sensor
FileOutPutStream
[daily question in summer] function of rogu p3742 UMI
Daily question -leetcode1175- permutation of prime numbers - Mathematics
Global and Chinese markets for business weather forecasting 2022-2028: Research Report on technology, participants, trends, market size and share
複制寶貝提示材質不能為空,如何解决?
智慧运维:基于 BIM 技术的可视化管理系统
Global and Chinese markets of Ethernet communication modules 2022-2028: Research Report on technology, participants, trends, market size and share
tar命令
QDataStream的簡單讀寫驗證
提高企业产品交付效率系列(1)—— 企业应用一键安装和升级
Some common commands of podman
LeetCode1497-检查数组对是否可以被 k 整除-数组-哈希表-计数
Vérification simple de la lecture et de l'écriture de qdatastream
More than one file was found with OS independent path ‘lib/armeabi-v7a/libyuv.so‘.
Single page application
Numeric amount plus comma; JS two methods of adding three digits and a comma to numbers; JS data formatting