Android RecyclerView
1|0Android RecyclerView
1|1介绍
RecyclerView
是 Android 的一个高级视图组件,旨在显示大量数据的列表或网格。相比于传统的 ListView
,RecyclerView
提供了更多的功能和灵活性。
1|0Adapter
Adapter
是 RecyclerView
的数据源,负责将数据绑定到 ViewHolder
上。常见的 Adapter
实现包括 RecyclerView.Adapter
和 RecyclerView.ViewHolder
。
1|0ViewHolder
ViewHolder
是一个用于缓存视图的对象,可以减少视图的重复查找。它持有对视图的引用,提升性能。
1|0LayoutManager
LayoutManager
负责测量和布局 RecyclerView
的子项。RecyclerView
提供了几种内置的 LayoutManager
,如 LinearLayoutManager
、GridLayoutManager
和 StaggeredGridLayoutManager
,也可以自定义 LayoutManager
。
1|0ItemDecoration
ItemDecoration
可以用于给 RecyclerView
的项添加装饰,比如边框、分隔线等。
1|0ItemAnimator
ItemAnimator
负责 RecyclerView
的动画效果,比如添加、删除或移动项时的动画。
1|2简单使用
1|0添加依赖
implementation 'androidx.recyclerview:recyclerview:1.1.0'
1|0在布局中添加RecyclerView控件
<androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="match_parent"/>
1|0为RecyclerView添加布局文件
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fruit_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:textSize="18sp"/>
1|0定义适配器与ViewHolder
public class FruitRecyclerAdapter extends RecyclerView.Adapter<MyViewHolder> { private Context context; public List<String> fruits; public FruitRecyclerAdapter(Context context,List<String> fruits){ this.context=context; this.fruits=fruits; } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { //onCreateViewHolder 方法负责创建视图项。它通过 View.inflate 方法将 fruit_item.xml 布局文件转换成 View 对象,并将其传递给 MyViewHolder。 View view = View.inflate(context, R.layout.fruit_item, null); //存在显示不全使用下面方法创建 //原因是“View.inflate()的第三个参数(父视图)如果为null,则意味着不会应用父视图的布局参数” //View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view,parent,false); return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { //onBindViewHolder 方法负责将数据绑定到视图项上。它获取当前项的数据并设置到 MyViewHolder 中对应的 TextView 控件上。 String fruit = fruits.get(position); holder.fruit.setText(fruit); } @Override public int getItemCount() { //getItemCount 方法返回数据集中项的总数,用于确定 RecyclerView 需要显示多少个视图项。 return fruits.size(); } } class MyViewHolder extends RecyclerView.ViewHolder{ //自定义的 ViewHolder 类,继承自 RecyclerView.ViewHolder,用于缓存视图组件,避免重复调用 findViewById。 TextView fruit; public MyViewHolder(@NonNull View itemView) { //MyViewHolder 构造函数,初始化 TextView 控件。 super(itemView); fruit = itemView.findViewById(R.id.fruit_text); } }
1|0设置RecyclerView
private RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //为RecyclerView添加数据集 List<String> fruits = new ArrayList<>(); fruits.add("苹果"); fruits.add("香蕉"); fruits.add("西瓜"); fruits.add("芒果"); recyclerView = findViewById(R.id.recycler); //设置 RecyclerView 的布局管理器为 LinearLayoutManager,这表示列表将以线性(垂直)方式显示。 recyclerView.setLayoutManager(new LinearLayoutManager(this)); //recyclerView.setLayoutManager(new LinearLayoutManager(this,RecyclerView.HORIZONTAL,false)); //这表示列表将以线性(水平)方式显示。false为是否倒序 //recyclerView.setLayoutManager(new GridLayoutManager(this,2,RecyclerView.VERTICAL,false));//列表将以网格(垂直)方式显示,2表示俩列 //recyclerView.setLayoutManager(new GridLayoutManager(this,2,RecyclerView.HORIZONTAL,false));//列表将以网格(水平)方式显示,2表示俩行 //设置 RecyclerView 的适配器 recyclerView.setAdapter(new FruitRecyclerAdapter(this,fruits)); // 添加系统默认的横向分隔线 DividerItemDecoration dividerItemDecoration = new DividerItemDecoration( recyclerView.getContext(), DividerItemDecoration.VERTICAL ); recyclerView.addItemDecoration(dividerItemDecoration); //----- 如果需要自定义分动画请自行百度 ----- // 配置 ItemAnimator(动画) DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); itemAnimator.setAddDuration(1000); // 设置添加动画的持续时间 itemAnimator.setRemoveDuration(1000); // 设置移除动画的持续时间 mRecyclerView.setItemAnimator(itemAnimator); //----- 如果需要自定义分动画请自行百度 ----- }
1|3使用自定义
1|0添加实体类
@Data @AllArgsConstructor public class Student { String name; int age; String sex; }
1|0添加布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:id="@+id/name" android:layout_marginHorizontal="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/sex" android:layout_marginHorizontal="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/age" android:layout_marginHorizontal="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
1|0修改适配器和viewholder
public class FruitRecyclerAdapter extends RecyclerView.Adapter<MyViewHolder> { private Context context; public List<Student> Students; public FruitRecyclerAdapter(Context context,List<Student> Students){ this.context=context; this.Students=Students; } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { //----- 修改 ----- View view = View.inflate(context, R.layout.layout_student_list, null); //----- 修改 ----- return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { //----- 修改 ----- Student student = Students.get(position); holder.name.setText(student.getName()); holder.age.setText(String.valueOf(student.getAge())); holder.sex.setText(student.getSex()); //----- 修改 ----- } @Override public int getItemCount() { return Students.size(); } } class MyViewHolder extends RecyclerView.ViewHolder{ //----- 修改 ----- TextView name; TextView age; TextView sex; public MyViewHolder(@NonNull View itemView) { super(itemView); name = itemView.findViewById(R.id.name); age = itemView.findViewById(R.id.age); sex = itemView.findViewById(R.id.sex); } //----- 修改 ----- }
1|0修改activity
//----- 修改 ------ List<Student> students=new ArrayList<>(); students.add(new Student("张三",21,"男")); students.add(new Student("李四",21,"女")); students.add(new Student("王五",21,"男")); //----- 修改 ------ /* 省略。。。 */ //----- 修改 ------ recyclerView.setAdapter(new FruitRecyclerAdapter(this,students)); //----- 修改 ------
1|4RecyclerView 点击事件
1|0方法 一
//在适配器中的onBindViewHolder添加代码 @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { Student student = Students.get(position); holder.name.setText(student.getName()); holder.age.setText(String.valueOf(student.getAge())); holder.sex.setText(student.getSex()); //----- 添加代码 ----- holder.linearLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context, "点击了姓名为:"+student.getName()+"的学生", Toast.LENGTH_SHORT).show(); } }); //----- 添加代码 ----- } //修改ViewHolder class MyViewHolder extends RecyclerView.ViewHolder{ TextView name; TextView age; TextView sex; //----- 添加代码 ----- LinearLayout linearLayout; //----- 添加代码 ----- public MyViewHolder(@NonNull View itemView) { super(itemView); name = itemView.findViewById(R.id.name); age = itemView.findViewById(R.id.age); sex = itemView.findViewById(R.id.sex); //----- 添加代码 ----- linearLayout=itemView.findViewById(R.id.itemsId); //----- 添加代码 ----- } } //修改布局文件 <?xml version="1.0" encoding="utf-8"?> <!-- 在代码中删除下面注释,xml中控件内部不支持注释 --> <LinearLayout //----- 添加代码 ----- android:id="@+id/itemsId" //----- 添加代码 ----- xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:id="@+id/name" android:layout_marginHorizontal="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/sex" android:layout_marginHorizontal="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/age" android:layout_marginHorizontal="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
1|0方法二
//修改viewholder class MyViewHolder extends RecyclerView.ViewHolder{ TextView name; TextView age; TextView sex; public MyViewHolder(@NonNull View itemView) { super(itemView); name = itemView.findViewById(R.id.name); age = itemView.findViewById(R.id.age); sex = itemView.findViewById(R.id.sex); } public void bind(Student student, int position, OnItemClickListener listener) { // 设置数据 name.setText(student.getName()); age.setText(String.valueOf(student.getAge())); sex.setText(student.getSex()); // 设置点击事件 itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (listener != null) { listener.onItemClick(position); } } }); } // 定义一个接口用于回调点击事件 public interface OnItemClickListener { void onItemClick(int position); } } //修改适配器onBindViewHolder方法 @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { holder.bind(Students.get(position), position, new MyViewHolder.OnItemClickListener() { @Override public void onItemClick(int position) { Toast.makeText(context,Students.get(position).getName(), Toast.LENGTH_SHORT).show(); } }); } /* //可以改写为 //定义全局属性 private OnItemClickListener listener; public FruitRecyclerAdapter(Context context,List<Student> Students,OnItemClickListener listener){ this.context=context; this.Students=Students; this.listener=listener; } //修改适配器onBindViewHolder方法 @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { holder.bind(Students.get(position), position,listener); } //在activity中绑定适配器时改为 recyclerView.setAdapter(new FruitRecyclerAdapter(this,students, new MyViewHolder.OnItemClickListener() { @Override public void onItemClick(int position) { Toast.makeText(this,Students.get(position).getName(), Toast.LENGTH_SHORT).show(); } })); */
1|0方法三
修改RecyclerView源码,在里面实现点击事件
1|5RecyclerView 下拉刷新
1|0添加依赖
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0'
1|0用SwipeRefreshLayout将RecyclerView包裹
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="match_parent"/> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
1|0为下拉加载绑定事件
//将Students与adapter设置为全局变量 public class MainActivity extends AppCompatActivity { //----- 设置为全局变量 ----- private RecyclerView recyclerView; private SwipeRefreshLayout swipeRefreshLayout; private List<Student> students; private RecyclerView.Adapter adapter; //----- 设置为全局变量 ----- @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //----- 修改 ----- students=new ArrayList<>(); //----- 修改 ----- /* 省略。。。 */ //----- 修改 ----- adapter = new FruitRecyclerAdapter(this,students); recyclerView.setAdapter(adapter); //----- 修改 ----- //swipeRefreshLayout绑定控件 swipeRefreshLayout=findViewById(R.id.swipeRefreshLayout); // 设置 SwipeRefreshLayout 的刷新监听 swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { // 这里进行下拉刷新操作 refreshData(); } }); //添加函数 private void refreshData() { // 模拟网络请求或数据加载 new Handler().postDelayed(new Runnable() { @Override public void run() { students.clear(); loadData(); // 重新加载数据 swipeRefreshLayout.setRefreshing(false); // 结束刷新 } }, 2000); // 模拟延迟2秒 } @SuppressLint("NotifyDataSetChanged") private void loadData() { // 模拟加载数据 for (int i = 0; i < 5; i++) { students.add(new Student("姓名"+(i+1),20+(i%5),i%2==0?"男":"女")); } adapter.notifyDataSetChanged(); } @SuppressLint("NotifyDataSetChanged") private void loadData() { // 模拟加载数据 for (int i = 0; i < 5; i++) { students.add(new Student("姓名"+(i+1),20+(i%5),i%2==0?"男":"女")); } adapter.notifyDataSetChanged(); }
1|6RecyclerView上拉加载
1|0添加回调接口
public interface LoadMoreCallback { void onLoadMore(); }
1|0实现 EndlessScrollListener来监听滚动事件,并触发加载更多的数据
public class EndlessScrollListener extends RecyclerView.OnScrollListener { private LinearLayoutManager layoutManager; private boolean isLoading = false; // 是否正在加载数据 private boolean isMoreDataAvailable = true; // 是否还有更多数据 private LoadMoreCallback loadMoreCallback;//回调函数 public EndlessScrollListener(LinearLayoutManager layoutManager, LoadMoreCallback loadMoreCallback) { this.layoutManager = layoutManager; this.loadMoreCallback = loadMoreCallback; } @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (dy > 0) { // 只处理向下滚动的情况 int visibleItemCount = layoutManager.getChildCount(); int totalItemCount = layoutManager.getItemCount(); int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition(); if (!isLoading && isMoreDataAvailable) { //检查我们是否需要加载更多数据 if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount) { isLoading = true; if (loadMoreCallback != null) { loadMoreCallback.onLoadMore(); // 加载更多 } } } } } public void setMoreDataAvailable(boolean moreDataAvailable) { this.isMoreDataAvailable = moreDataAvailable; } public void setLoading(boolean loading) { this.isLoading = loading; } }
1|0activity绑定EndlessScrollListener滚动事件
//实现回调函数 public class MainActivity extends AppCompatActivity implements LoadMoreCallback { private SwipeRefreshLayout swipeRefreshLayout; private RecyclerView recyclerView; private MyAdapter adapter; private List<MyItem> itemList; private EndlessScrollListener scrollListener; private boolean hasMoreData = true; // 控制是否还有更多数据 @Override protected void onCreate(Bundle savedInstanceState) { //----- 省略 ----- // 初始化并添加滚动监听器 scrollListener = new EndlessScrollListener((LinearLayoutManager) recyclerView.getLayoutManager(), this); recyclerView.addOnScrollListener(scrollListener); //----- 省略 ----- } @Override public void onLoadMore() { if (hasMoreData) { // 模拟加载更多数据 new Handler().postDelayed(new Runnable() { @Override public void run() { loadMoreData(); scrollListener.setLoading(false); // 加载完成 } }, 1000); // 模拟延迟1秒 } } private void loadMoreData() { // 模拟加载更多数据 int start = students.size(); for (int i = start; i < start + 10; i++) { students.add(new Student("更多 ----- 姓名"+(i+1),20+(i%5),i%2==0?"男":"女")); } adapter.notifyDataSetChanged(); // 控制是否还有更多数据 if (students.size() > 100) { // 假设100个数据后就没有更多数据了 hasMoreData = false; } }
1|7总结
RecyclerView
是一个功能强大且灵活的视图组件,适用于处理复杂的数据展示需求。通过合理配置 Adapter
、ViewHolder
、LayoutManager
等组件,可以高效地展示和管理大量数据。同时,支持自定义布局、点击事件处理以及下拉刷新等功能
2|0代码地址
https://gitee.com/lxj_dear/recycler-view
__EOF__

本文作者:疾风不问归途
本文链接:https://www.cnblogs.com/20lxj666/p/18334298.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/20lxj666/p/18334298.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性