当前位置:网站首页>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.
边栏推荐
- Some common commands of podman
- C WPF uses dockpanel to realize screenshot box
- Day 05 - file operation function
- Unit testing with mongodb
- Summary of spanner's paper
- Cockroachdb: the resistant geo distributed SQL database paper reading notes
- busybox生成的东西
- LRU cache for leveldb source code analysis
- CockroachDB: The Resilient Geo-Distributed SQL Database 论文阅读笔记
- Txncoordsender of cockroachdb distributed transaction source code analysis
猜你喜欢
Intelligent operation and maintenance: visual management system based on BIM Technology
Summary of spanner's paper
Leetcode1497- check whether array pairs can be divided by K - array - hash table - count
LeetCode1497-检查数组对是否可以被 k 整除-数组-哈希表-计数
CockroachDB 分布式事务源码分析之 TxnCoordSender
Manually implement a simple stack
[RootersCTF2019]babyWeb
One click deployment of highly available emqx clusters in rainbow
Application and principle of ThreadPoolExecutor thread pool
Principle, technology and implementation scheme of data consistency in distributed database
随机推荐
Variable binding and deconstruction for rudimentary rust
AcWing 888. Finding combinatorial number IV (the problem of finding combinatorial number with high precision)
Software intelligence: the "world" and "boundary" of AI sentient beings in AAAs system
JS random verification code
Usage and principle of synchronized
More than one file was found with OS independent path ‘lib/armeabi-v7a/libyuv.so‘.
Tcp/ip explanation (version 2) notes / 3 link layer / 3.2 Ethernet and IEEE 802 lan/man standards
Simple read / write verification of qdatastream
[RootersCTF2019]babyWeb
El cascade echo failed; El cascader does not echo
Memtable for leveldb source code analysis
Copier le matériel de conseils de bébé ne peut pas être vide, comment résoudre?
Global and Chinese markets of superconductor 2022-2028: Research Report on technology, participants, trends, market size and share
Distributed transactions - Solutions
Lock free concurrency of JUC (leguan lock)
Global and Chinese markets for soft ferrite cores 2022-2028: Research Report on technology, participants, trends, market size and share
Thread process foundation of JUC
Set集合详细讲解
Leetcode522- longest special sequence ii- hash table - String - double pointer
AcWing 887. Finding combinatorial number III (Lucas theorem)