RecyclerView
一、RecyclerView
RecyclerView是Android 5.0推出的,是support-v7包中的新组件,它被用来代替ListView和GridView,并且能够实现瀑布流的布局,更加高级并且更加灵活,提供更为高效的回收复用机制,同时实现管理与视图的解耦合。
官方文档解释:
A flexible view for providing a limited window into a large data set.
二、新版本:
直接在所要用到的xml界面看就行,右上角找design
。
然后进去以后找下图的红框,因为我已经下载好了就没有显示下载按钮,你如果没有点下载的图标就可以。
点住想要插入的控件拖进去就创建成功啦!
或者直接在右侧的code界面输入控件代码也可以!
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
二、RecyclerView基本介绍:
通过使用RecyclerView控件,我们可以在APP中创建带有Material Design风格的复杂列表。RecyclerView控件和ListView的原理有很多相似的地方,都是维护少量的View来进行显示大量的数据
,不过RecyclerView控件比ListView更加高级并且更加灵活。当我们的数据因为用户事件或者网络事件发生改变的时候也能很好的进行显示。
和ListView不同的是,RecyclerView不用在负责Item的显示相关的功能,在这边所有有关布局,绘制,数据绑定等都被分拆成不同的类进行管理,下面我这边会一个个的进行讲解。同时RecyclerView控件提供了以下两种方法来进行简化和处理大数量集合:
1. 采用LayoutManager来处理Item的布局
2. 提供Item操作的默认动画,例如在增加或者删除item的时候
你也可以自定义LayoutManager或者设置添加/删除的动画,整体的RecyclerView结构图如下:
为了使用RecyclerView控件,我们需要创建一个Adapter和一个LayoutManager:
Adapter
:继承自RecyclerView.Adapetr
类,主要用来将数据和布局item
进行绑定。LayoutManager
:布局管理器,设置每一项view在RecyclerView中的位置布局
以及控件item view的显示或者隐藏
。当View重用或者回收的时候,LayoutManger都会向Adapter来请求新的数据来进行替换原来数据的内容。这种回收重用的机制可以提供性能,避免创建很多的view或者是频繁的调用findViewById方法。这种机制和ListView还是很相似的。
RecyclerView提供了三种内置的LayoutManager:
- 1、
LinearLayoutManager
:线性布局,横向或者纵向滑动列表 - 2.、
GridLayoutManager
:表格布局 - 3、
StaggeredGridLayoutManager
:流式布局,例如瀑布流效果
当然除了上面的三种内部布局之外,我们还可以继承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基本实现:
我这边实例采用Android Studio 1.3.2。
1、添加库依赖:
想要使用recycleview控件,首先需要在项目的build.gradle文件添加相应的依赖库,具体如下:
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.blankj:utilcode:1.28.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
2.添加布局
在activity_main.xml中添加如下代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
</LinearLayout >
3.新建一个item_dome.xml,为RecyclerView内的元素设定xml样式
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:id="@+id/text_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="测试"
android:layout_marginRight="1dp"
android:layout_marginLeft="1dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="1dp"
android:textColor="@android:color/holo_red_dark"
android:background="@android:color/holo_blue_dark" />
</LinearLayout>
4、自定义一个适配器继承RecyclerView.Adapter来进行创建item view以及绑定数据
步骤:
-
1.创建适配器类继承自RecyclerView.Adapter,泛型传入RecyclerView.ViewHolder类。
-
2.创建内部类即RecyclerView.ViewHolder类的子类,并初始化item的控件。
-
3.重写RecyclerView.Adapter类的相关方法。
package com.example.helloworld;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
/*
① 创建一个继承RecyclerView.Adapter<VH>的Adapter类
② 创建一个继承RecyclerView.ViewHolder的静态内部类
③ 在Adapter中实现3个方法:
onCreateViewHolder()
onBindViewHolder()
getItemCount()
*/
public class RecycleAdapterDome extends RecyclerView.Adapter<RecycleAdapterDome.MyViewHolder>{
private Context context;
private List<String> list;
private View inflater;
//构造方法,传入数据,即把展示的数据源传进来,并且复制给一个全局变量,以后的操作都在该数据源上进行
public RecycleAdapterDome(Context context, List<String> list){
this.context = context;
this.list = list;
}
//由于RecycleAdapterDome继承自RecyclerView.Adapter,则必须重写onCreateViewHolder(),onBindViewHolder(),getItemCount()
//onCreateViewHolder()方法用于创建ViewHolder实例,我们在这个方法将item_dome.xml布局加载进来
//然后创建一个ViewHolder实例,并把加载出来的布局传入到构造函数,最后将实例返回
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//创建ViewHolder,返回每一项的布局
inflater = LayoutInflater.from(context).inflate(R.layout.item_dome,parent,false);
MyViewHolder myViewHolder = new MyViewHolder(inflater);
return myViewHolder;
}
//onBindViewHolder()方法用于对RecyclerView子项数据进行赋值,会在每个子项被滚动到屏幕内的时候执行
//这里我们通过position参数的得到当前项的实例,然后将数据设置到ViewHolder的TextView即可
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
//将数据和控件绑定
holder.textView.setText(list.get(position));
}
//getItemCount()告诉RecyclerView一共有多少个子项,直接返回数据源的长度。
@Override
public int getItemCount() {
//返回Item总条数
return list.size();
}
//内部类,绑定控件
class MyViewHolder extends RecyclerView.ViewHolder{
TextView textView;
public MyViewHolder(View itemView) {//这个view参数就是recyclerview子项的最外层布局
super(itemView);
//可以通过findViewById方法获取布局中的TextView
textView = (TextView) itemView.findViewById(R.id.text_view);
}
}
}
5.MainActivity.java中
在Activity中获取RecyclerView控件然后进行设置LayoutManger以及Adapter即可,和ListView的写法有点类似:
步骤:
1.获取RecyclerView对象 。
2.初始化数据 。
3.适配器实例化 。
4.设置LayoutManager
5. 设置Adapter 。
package com.example.helloworld;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Context;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;//声明RecyclerView
private RecycleAdapterDome adapterDome;//声明适配器
private Context context;
private List<String> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
//开始设置RecyclerView
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
//添加数据
list = new ArrayList<>();
for (int i=0;i<10;i++){
list.add("这是第"+i+"个测试");
}
//
adapterDome = new RecycleAdapterDome(context,list);
/*
与ListView效果对应的可以通过LinearLayoutManager来设置
与GridView效果对应的可以通过GridLayoutManager来设置
与瀑布流对应的可以通过StaggeredGridLayoutManager来设置
*/
//LinearLayoutManager manager = new LinearLayoutManager(context,LinearLayoutManager.VERTICAL,false);
//创建线性布局
LinearLayoutManager manager = new LinearLayoutManager(context);
//垂直方向
manager.setOrientation(LinearLayoutManager.VERTICAL);
//RecyclerView.LayoutManager manager = new LinearLayoutManager(context,LinearLayoutManager.VERTICAL,false);
//GridLayoutManager manager1 = new GridLayoutManager(context,2);
//manager1.setOrientation(GridLayoutManager.VERTICAL);
//StaggeredGridLayoutManager manager2 = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
//给RecyclerView设置布局管理器
recyclerView.setLayoutManager(manager);
//创建适配器,并且设置
recyclerView.setAdapter(adapterDome);
}
}
运行结果:
这个自定义Adapter和我们在使用Listview时候的Adapter相比还是有点不太一样的,首先这边我们需要继承RecyclerView.Adaper
类,然后实现两个重要的方法onBindViewHodler()
以及onCreateViewHolder()
,这边我们看出来区别,使用RecyclerView控件我们就可以把Item View视图创建和数据绑定这两步进行分来进行管理
,用法就更加方便而且灵活了,并且我们可以定制打造千变万化的布局。同时这边我们还需要创建一个ViewHolder类,该类必须继承自RecyclerView.ViewHolder类,现在Google也要求我们必须要实现ViewHolder来承载Item的视图。
package com.example.helloworld;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class RecycleAdapterDome extends RecyclerView.Adapter<RecycleAdapterDome.MyViewHolder>{
private Context context;
private List<String> list;
private View inflater;
//构造方法,传入数据
public RecycleAdapterDome(Context context, List<String> list){
this.context = context;
this.list = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//创建ViewHolder,返回每一项的布局
inflater = LayoutInflater.from(context).inflate(R.layout.item_dome,parent,false);
MyViewHolder myViewHolder = new MyViewHolder(inflater);
myViewHolder.demoView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
int position = myViewHolder.getAdapterPosition();
String test = list.get(position);
Toast.makeText(v.getContext(),"you clicked " + test,Toast.LENGTH_SHORT).show();
}
});
return myViewHolder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
//将数据和控件绑定
holder.textView.setText(list.get(position));
}
@Override
public int getItemCount() {
//返回Item总条数
return list.size();
}
//内部类,绑定控件
class MyViewHolder extends RecyclerView.ViewHolder{
View demoView;
TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
demoView = itemView;
textView = (TextView) itemView.findViewById(R.id.text_view);
}
}
}
参考
1、https://www.jianshu.com/p/8379ea2bc63b
2、https://blog.csdn.net/Zhang_713/article/details/109428508
3、https://blog.csdn.net/weixin_43468667/article/details/89435098