Android RecyclerView

1|0Android RecyclerView

1|1介绍

RecyclerView 是 Android 的一个高级视图组件,旨在显示大量数据的列表或网格。相比于传统的 ListViewRecyclerView 提供了更多的功能和灵活性。

1|0Adapter

AdapterRecyclerView 的数据源,负责将数据绑定到 ViewHolder 上。常见的 Adapter 实现包括 RecyclerView.AdapterRecyclerView.ViewHolder

1|0ViewHolder

ViewHolder 是一个用于缓存视图的对象,可以减少视图的重复查找。它持有对视图的引用,提升性能。

1|0LayoutManager

LayoutManager 负责测量和布局 RecyclerView 的子项。RecyclerView 提供了几种内置的 LayoutManager,如 LinearLayoutManagerGridLayoutManagerStaggeredGridLayoutManager,也可以自定义 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 是一个功能强大且灵活的视图组件,适用于处理复杂的数据展示需求。通过合理配置 AdapterViewHolderLayoutManager 等组件,可以高效地展示和管理大量数据。同时,支持自定义布局、点击事件处理以及下拉刷新等功能

2|0代码地址

https://gitee.com/lxj_dear/recycler-view


__EOF__

本文作者疾风不问归途
本文链接https://www.cnblogs.com/20lxj666/p/18334298.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   疾风不问归途  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示