目次
前言
RecyclerView控件
数据适配器
结构管理器
使用RecyclerView
创建XML结构文件
创建ReActivity类
创建数据适配器
onCreateViewHolder
onBindViewHolder
完整代码
补充知识
ItemDecoration
前言
在前一篇中,我们讲解了ListView控件,那么本篇我们就来讲解RecyclerView控件
RecyclerView控件
与ListView类似,RecyclerView控件同样也是以列表的形式将数据进行展示,都是为了维护少量的View来进行显示大量的数据。是在android5.0之后新添的控件,用来替代传统的ListView和GridView控件的。
与传统的ListView不同,RecyclerView能通过LayoutManager类来实现横向或者竖向的列表效果、瀑布流效果和GridView效果,而ListView只能实现竖直的列表效果。
格式如下:
- <androidx.recyclerview.widget.RecyclerView
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
复制代码 我们 可以通过在Patale中找到RecylcerView,将其拉到XML文件中
当然,我们也可以手动添加:
数据适配器
RecyclerView控件使用的是RecyclerView.Adapter,该数据适配器将BaseAdapter中的getView()方法拆解为onCreateViewHolder()方法和onBindViewHolder()方法,强制使用ViewHolder类,使代码更加规范化。
结构管理器
LayoutManager结构管理器用来设置每一项view在RecyclerView中的位置结构,以及控件item view的显示或隐藏。当View重用或者回收的时候,LayoutManager都会向Adapter来请求新的数据进行替换原来的数据的内容。这种回收复用机制可以提供性能,克制创建许多的view或者是频仍的调用findViewById()方法。
RcyclerView提供了三种内置的LayoutManager:
- LinearLayoutManager:线性结构,横向或者纵向滑动列表
- GridLayoutManager:网格结构
- StaggerdGridLayoutManager:流式结构,如瀑布流效果。
当然,我们也可以通过继续RecyclerView.LayoutManager来实现一个自界说的LayoutManager。
Animations(动画)效果:
- RecyclerView对于Item的添加和删除是默认开启动画的,我们也可以通过RecyclerView.ItemAnimator类来定制动画,再通过RecyclerView.setItemAnimator()方法来使用
以下是RecyclerView的一些相关类:
类名 | 阐明 | RecyclerView.Adapter | 可以托管数据集合,为每一项Item创建视图并且绑定数据 | RecyclerView.ViewHolder | 承载Item视图的子结构 | RecyclerView.LayoutManager | 负责Item视图的结构的显示管理 | RecyclerView.ItemDecoration | 给每一项Item视图添加子View,例如进行画分割线等 | RecyclerView.ItemAnimator | 负责处理数据添加或者删除时候的动画效果 | 使用RecyclerView
创建XML结构文件
这里我选择创建一个名为recycle_list.xml的结构文件。
这里我们选择模仿聊天的界面,那么起首我们需要实现一个聊天的界面,就在上面创建的结构中实现。效果图如下:
- <?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="wrap_content"
- android:layout_margin="16dp">
- <ImageView
- android:id="@+id/tv"
- android:src="@mipmap/ic_launcher"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- <LinearLayout
- android:layout_width="200dp"
- android:layout_height="match_parent"
- android:layout_marginLeft="10dp"
- android:orientation="vertical">
- <TextView
- android:id="@+id/tv_name"
- android:text="李四"
- android:textStyle="bold"
- android:textSize="20sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- <TextView
- android:id="@+id/news"
- android:text="李四,你今天在干嘛呢?"
- android:textSize="15sp"
- android:layout_marginTop="15sp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- </LinearLayout>
- <TextView
- android:id="@+id/tv_time"
- android:gravity="end"
- android:text="24/8/25\n12:00"
- android:textColor="#999999"
- android:textSize="15sp"
- android:layout_width="wrap_content"
- android:layout_weight="1"
- android:layout_height="match_parent"/>
- </LinearLayout>
复制代码 同时,我们可以创建一个recycle_main.xml结构用来显示聊天界面,在其中放入RecyclerView控件。
- <?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">
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/recyclerView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
- </LinearLayout>
复制代码 创建ReActivity类
我们既然已经把结构文件做好,那么现在就是有关java的代码了,我们需要创建一个ReActivity类,在里面来进行绑定结构文件等操作。
- import android.os.Bundle;
- import androidx.annotation.Nullable;
- import androidx.appcompat.app.AppCompatActivity;
- import androidx.recyclerview.widget.RecyclerView;
- public class ReActivity extends AppCompatActivity {
- private RecyclerView recyclerView;
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.recycle_main);
- Init();
- }
- private void Init() {
- recyclerView = findViewById(R.id.recyclerView);//初始化recyclerView
- }
- }
复制代码 创建数据适配器
在上面,我们已经把聊天的界面以及RecyclerView控件创建出来了,那么接下来我们就来自界说一个适配器继续RecyclerView.Adapter来创建item view以及绑定数据.
onCreateViewHolder
步调:
- 创建适配器类继续RecyclerView.Adapter,传入泛型
- 创建内部类即RecyclerView.ViewHolder的子类,并初始化item控件。
- 重写RecyclerView.Adapter类的相关方法。
这里我们使用View.inflate来加载v,并将v传给内部类MyAdapter(本身实现)继续实例化。
- private View v;
- private MyAdapter myAdapter;
- @NonNull
- @Override
- public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- v = View.inflate(ReActivity.this,R.layout.recycle_list,null);
- myAdapter = new MyAdapter(v);
- return myAdapter;
- }
复制代码 这里创建一个内部类MyAdapter继续ViewHolder,绑定传进来的v的控件。
- class MyAdapter extends RecyclerView.ViewHolder {
- TextView name, news, time;
- ImageView image;
- public MyAdapter(@NonNull View itemView) {
- super(itemView);
- name = itemView.findViewById(R.id.tv_name);
- news = itemView.findViewById(R.id.news);
- time = itemView.findViewById(R.id.tv_time);
- }
- }
复制代码 onBindViewHolder
- 将获取到的数据设置到对应的控件上。
- 传入类的holder和position
position相当于下标,既然需要获取类的数据,那么我们需要一个构造方法来初始化类的数据
- private final Context context;
- private final ArrayList nameList,timeList,newsList;
- public Adapter(Context context, ArrayList nameList, ArrayList newsList, ArrayList timeList){
- this.context = context;
- this.nameList = nameList;
- this.newsList = newsList;
- this.timeList = timeList;
- }
复制代码 到这,我们已经把自界说的适配器Adapter实现完成,完整代码:
- /**
- * RecyclerView的适配器类
- */
- class Adapter extends RecyclerView.Adapter<Adapter.MyAdapter> {
- private Context context;
- private ArrayList nameList, newsList, timeList;
- /**
- * Adapter构造方法
- * @param context 上下文环境,此处为ReActivity实例
- * @param nameList 名称数据列表
- * @param newsList 消息数据列表
- * @param timeList 时间数据列表
- */
- public Adapter(Context context, ArrayList nameList, ArrayList newsList, ArrayList timeList){
- this.context = context;
- this.nameList = nameList;
- this.newsList = newsList;
- this.timeList = timeList;
- }
- /**
- * 创建ViewHolder
- * @param parent 父容器,用于容纳RecyclerView项视图
- * @param viewType 视图类型,此处未使用
- * @return 创建的ViewHolder实例
- */
- @NonNull
- @Override
- public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View v = View.inflate(ReActivity.this,R.layout.recycle_list,null); // 加载RecyclerView项布局文件
- MyAdapter myAdapter = new MyAdapter(v); // 创建ViewHolder
- return myAdapter;
- }
- /**
- * 绑定ViewHolder数据
- * @param holder ViewHolder实例,用于展示数据
- * @param position 数据源中的位置
- */
- @Override
- public void onBindViewHolder(@NonNull MyAdapter holder, int position) {
- holder.name.setText(nameList.get(position).toString()); // 设置名称文本
- holder.news.setText(newsList.get(position).toString()); // 设置消息文本
- holder.time.setText(timeList.get(position).toString()); // 设置时间文本
- }
- /**
- * 返回数据源中项的数量
- * @return 数据源大小
- */
- @Override
- public int getItemCount() {
- return nameList.size();
- }
- /**
- * RecyclerView ViewHolder子类
- */
- class MyAdapter extends RecyclerView.ViewHolder {
- TextView name, news, time;
- ImageView image;
- /**
- * MyAdapter构造方法,用于初始化ViewHolder中的视图组件
- * @param itemView RecyclerView项的根视图
- */
- public MyAdapter(@NonNull View itemView) {
- super(itemView);
- name = itemView.findViewById(R.id.tv_name); // 初始化名称文本视图
- news = itemView.findViewById(R.id.news); // 初始化消息文本视图
- time = itemView.findViewById(R.id.tv_time); // 初始化时间文本视图
- }
- }
- }
复制代码 接下来,我们就在我们界说的Init()方法中来实例化这些类以及调用相关的方法。
- 起首实例化存储数据的三个ArrayList,分别存储用户名,信息,时间。并模仿天生一些数据。
- 创建Adapter对象并将上面三个ArratList传入
- 创建线性结构管理器,并给前面的rercyclerView设置结构为线性结构。
- 给rercyclerView设置每一项的动画,并且设置分割线和适配器
- /**
- * 初始化方法,用于初始化RecyclerView组件及适配器
- */
- private void Init() {
- recyclerView = findViewById(R.id.recyclerView); // 初始化RecyclerView组件
- // 初始化存储数据的ArrayList
- ArrayList names = new ArrayList();
- ArrayList newsList = new ArrayList();
- ArrayList timeList = new ArrayList();
- // 循环生成模拟数据
- for(int i=0;i<50;i++){
- names.add("00"+i);
- newsList.add("你今天在干嘛呢?");
- timeList.add("2020-01-01 \n15:"+i);
- }
- // 创建Adapter实例并传入数据源
- Adapter adapter = new Adapter(this ,names,newsList,timeList);
- // 创建LinearLayoutManager实例,用于管理RecyclerView的布局
- LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
- recyclerView.setLayoutManager(linearLayoutManager); // 设置RecyclerView的布局管理器
- recyclerView.setItemAnimator(new DefaultItemAnimator()); // 设置RecyclerView的项动画
- recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL)); // 添加分割线装饰
- recyclerView.setAdapter(adapter); // 设置RecyclerView的适配器
- }
复制代码 完整代码
ReActivity.java
- import android.content.Context;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import androidx.recyclerview.widget.DefaultItemAnimator;import androidx.recyclerview.widget.DividerItemDecoration;import androidx.recyclerview.widget.LinearLayoutManager;import androidx.recyclerview.widget.RecyclerView;import java.util.ArrayList;// ReActivity类继续自AppCompatActivity,用于展示RecyclerView实现的列表界面public class ReActivity extends AppCompatActivity { // 声明RecyclerView对象 private RecyclerView recyclerView; /** * onCreate方法,在活动创建时调用 * @param savedInstanceState 大概存在的保存实例状态Bundle,此处为可空 */ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.recycle_main); // 设置活动的结构文件 Init(); // 初始化组件和数据 } /**
- * 初始化方法,用于初始化RecyclerView组件及适配器
- */
- private void Init() {
- recyclerView = findViewById(R.id.recyclerView); // 初始化RecyclerView组件
- // 初始化存储数据的ArrayList
- ArrayList names = new ArrayList();
- ArrayList newsList = new ArrayList();
- ArrayList timeList = new ArrayList();
- // 循环生成模拟数据
- for(int i=0;i<50;i++){
- names.add("00"+i);
- newsList.add("你今天在干嘛呢?");
- timeList.add("2020-01-01 \n15:"+i);
- }
- // 创建Adapter实例并传入数据源
- Adapter adapter = new Adapter(this ,names,newsList,timeList);
- // 创建LinearLayoutManager实例,用于管理RecyclerView的布局
- LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
- recyclerView.setLayoutManager(linearLayoutManager); // 设置RecyclerView的布局管理器
- recyclerView.setItemAnimator(new DefaultItemAnimator()); // 设置RecyclerView的项动画
- recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL)); // 添加分割线装饰
- recyclerView.setAdapter(adapter); // 设置RecyclerView的适配器
- } /**
- * RecyclerView的适配器类
- */
- class Adapter extends RecyclerView.Adapter<Adapter.MyAdapter> {
- private Context context;
- private ArrayList nameList, newsList, timeList;
- /**
- * Adapter构造方法
- * @param context 上下文环境,此处为ReActivity实例
- * @param nameList 名称数据列表
- * @param newsList 消息数据列表
- * @param timeList 时间数据列表
- */
- public Adapter(Context context, ArrayList nameList, ArrayList newsList, ArrayList timeList){
- this.context = context;
- this.nameList = nameList;
- this.newsList = newsList;
- this.timeList = timeList;
- }
- /**
- * 创建ViewHolder
- * @param parent 父容器,用于容纳RecyclerView项视图
- * @param viewType 视图类型,此处未使用
- * @return 创建的ViewHolder实例
- */
- @NonNull
- @Override
- public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View v = View.inflate(ReActivity.this,R.layout.recycle_list,null); // 加载RecyclerView项布局文件
- MyAdapter myAdapter = new MyAdapter(v); // 创建ViewHolder
- return myAdapter;
- }
- /**
- * 绑定ViewHolder数据
- * @param holder ViewHolder实例,用于展示数据
- * @param position 数据源中的位置
- */
- @Override
- public void onBindViewHolder(@NonNull MyAdapter holder, int position) {
- holder.name.setText(nameList.get(position).toString()); // 设置名称文本
- holder.news.setText(newsList.get(position).toString()); // 设置消息文本
- holder.time.setText(timeList.get(position).toString()); // 设置时间文本
- }
- /**
- * 返回数据源中项的数量
- * @return 数据源大小
- */
- @Override
- public int getItemCount() {
- return nameList.size();
- }
- /**
- * RecyclerView ViewHolder子类
- */
- class MyAdapter extends RecyclerView.ViewHolder {
- TextView name, news, time;
- ImageView image;
- /**
- * MyAdapter构造方法,用于初始化ViewHolder中的视图组件
- * @param itemView RecyclerView项的根视图
- */
- public MyAdapter(@NonNull View itemView) {
- super(itemView);
- name = itemView.findViewById(R.id.tv_name); // 初始化名称文本视图
- news = itemView.findViewById(R.id.news); // 初始化消息文本视图
- time = itemView.findViewById(R.id.tv_time); // 初始化时间文本视图
- }
- }
- }}
复制代码 结合前面的两个XML结构,运行即可得到:
补充知识
ItemDecoration
在使用RecyclerView的时候,如果我们想要设置分割线,那么我们可以通过ItemDecoration。例如:
- DividerItemDecoration decoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL);分割线
- recyclerView.addItemDecoration(decoration); // 添加分割线装饰
复制代码
Item动画
在RecyclerView中提供了默认的IntemAnimator实现类: DefaulttemAnimator。我们可以借助该类帮我们实现一些动画。
- DefaultItemAnimator animator = new DefaultItemAnimator();
- animator.setAddDuration(1000);
- animator.setRemoveDuration(1000);
- recyclerView.setItemAnimator(animator); // 设置RecyclerView的项动画
复制代码 在前面的基础上,在recycle_main.xml聊天界面的上部添加两个按钮(添加和删除)
- <LinearLayout
- android:layout_marginLeft="80dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
- <Button
- android:id="@+id/add"
- android:text="添加Item"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <Button
- android:id="@+id/del"
- android:text="删除Item"
- android:layout_marginLeft="60dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
复制代码 同时在ReActivity类中添加对应点击变乱(由于代码有改动,以是这里直接放全部代码):
- package com.example.newapptext1;import android.content.Context;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import androidx.recyclerview.widget.DefaultItemAnimator;import androidx.recyclerview.widget.DividerItemDecoration;import androidx.recyclerview.widget.LinearLayoutManager;import androidx.recyclerview.widget.RecyclerView;import java.util.ArrayList;// ReActivity类继续自AppCompatActivity,用于展示RecyclerView实现的列表界面public class ReActivity extends AppCompatActivity implements View.OnClickListener { // 声明RecyclerView对象 private RecyclerView recyclerView; private Adapter adapter; private ArrayList names; private ArrayList newsList; private ArrayList timeList; /** * onCreate方法,在活动创建时调用 * @param savedInstanceState 大概存在的保存实例状态Bundle,此处为可空 */ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.recycle_main); // 设置活动的结构文件 Init(); // 初始化组件和数据 } /** * 初始化方法,用于初始化RecyclerView组件及适配器 */ private void Init() { recyclerView = findViewById(R.id.recyclerView); // 初始化RecyclerView组件 // 初始化存储数据的ArrayList names = new ArrayList(); newsList = new ArrayList(); timeList = new ArrayList(); // 循环天生模仿数据 for(int i=0;i<5;i++){ names.add("00"+i); newsList.add("你今天在干嘛呢?"); timeList.add("2020-01-01 \n15:"+i); } // 创建Adapter实例并传入数据源 adapter = new Adapter(this , names, newsList, timeList); // 创建LinearLayoutManager实例,用于管理RecyclerView的结构 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); // 设置垂直方向 recyclerView.setLayoutManager(linearLayoutManager); // 设置RecyclerView的结构管理器 DefaultItemAnimator animator = new DefaultItemAnimator();
- animator.setAddDuration(1000);
- animator.setRemoveDuration(1000);
- recyclerView.setItemAnimator(animator); // 设置RecyclerView的项动画 DividerItemDecoration decoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL);分割线
- recyclerView.addItemDecoration(decoration); // 添加分割线装饰 recyclerView.setAdapter(adapter); // 设置RecyclerView的适配器 //添加点击变乱 findViewById(R.id.add).setOnClickListener(this); findViewById(R.id.del).setOnClickListener(this); } @Override public void onClick(View view) { // 判断点击的视图是否为添加按钮 if(view.getId()==R.id.add){ // 向列表中添加新的名字和消息,用于模仿新消息的到来 names.add(1,"新添"); newsList.add(1,"你在干嘛呢?"); timeList.add(1,"2020-01-01 \n15:00"); // 通知适配器插入新项,以便更新UI adapter.notifyItemInserted(1); } else if(view.getId()==R.id.del){ // 判断点击的视图是否为删除按钮 // 从名字、消息和时间列表中移除指定位置的元素,以模仿数据删除操作 names.remove(1); newsList.remove(1); timeList.remove(1); // 通知适配器移除项,以便更新UI adapter.notifyItemRemoved(1); } } /**
- * RecyclerView的适配器类
- */
- class Adapter extends RecyclerView.Adapter<Adapter.MyAdapter> {
- private Context context;
- private ArrayList nameList, newsList, timeList;
- /**
- * Adapter构造方法
- * @param context 上下文环境,此处为ReActivity实例
- * @param nameList 名称数据列表
- * @param newsList 消息数据列表
- * @param timeList 时间数据列表
- */
- public Adapter(Context context, ArrayList nameList, ArrayList newsList, ArrayList timeList){
- this.context = context;
- this.nameList = nameList;
- this.newsList = newsList;
- this.timeList = timeList;
- }
- /**
- * 创建ViewHolder
- * @param parent 父容器,用于容纳RecyclerView项视图
- * @param viewType 视图类型,此处未使用
- * @return 创建的ViewHolder实例
- */
- @NonNull
- @Override
- public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View v = View.inflate(ReActivity.this,R.layout.recycle_list,null); // 加载RecyclerView项布局文件
- MyAdapter myAdapter = new MyAdapter(v); // 创建ViewHolder
- return myAdapter;
- }
- /**
- * 绑定ViewHolder数据
- * @param holder ViewHolder实例,用于展示数据
- * @param position 数据源中的位置
- */
- @Override
- public void onBindViewHolder(@NonNull MyAdapter holder, int position) {
- holder.name.setText(nameList.get(position).toString()); // 设置名称文本
- holder.news.setText(newsList.get(position).toString()); // 设置消息文本
- holder.time.setText(timeList.get(position).toString()); // 设置时间文本
- }
- /**
- * 返回数据源中项的数量
- * @return 数据源大小
- */
- @Override
- public int getItemCount() {
- return nameList.size();
- }
- /**
- * RecyclerView ViewHolder子类
- */
- class MyAdapter extends RecyclerView.ViewHolder {
- TextView name, news, time;
- ImageView image;
- /**
- * MyAdapter构造方法,用于初始化ViewHolder中的视图组件
- * @param itemView RecyclerView项的根视图
- */
- public MyAdapter(@NonNull View itemView) {
- super(itemView);
- name = itemView.findViewById(R.id.tv_name); // 初始化名称文本视图
- news = itemView.findViewById(R.id.news); // 初始化消息文本视图
- time = itemView.findViewById(R.id.tv_time); // 初始化时间文本视图
- }
- }
- }}
复制代码 运行之后可以得到:
当然,尚有个革新功能,后面再跟各人讲。
以上就是本篇所有内容,如有不敷,欢迎指正~
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |