RecyclerView 相比于ListView,更比较灵活,
可以应用不同的布局方式,比如LinearLayout、GridLayout、StagGridLayout等
步骤
1、引入RecyclerView依赖包
Frist\app\build.gradle中的dependencies{}添加RecyclerView
//添加RecyclerView的依赖包
implementation 'androidx.recyclerview:recyclerview:1.1.0'
这个依赖包在学习教材中提示需要引入,但是实际练习过程中,没有引入也没有报错。估计是和我本地软件有关吧。
但是建议还是都引入依赖包
2、准备主Layout布局
res/layout/activity_relative_layout.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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".RecyclerViewActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
与ListView比较:
可以看出就是使用控件类型不同,
ListView直接使用ListView就可以
而RecyclerView 需要使用androidx.recyclerview.widget.RecyclerView(属于依赖包)。
3、新建RecyclerView的itm布局
res/layout/recyler_view_itm.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="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/tv_rv_itm_one"
android:text="2332"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25px"
/>
</LinearLayout>
与ListView比较:
可以看出与ListView的itm 布局,并无不同
4、新建bean类
com/pha/first/bean/RecylerBean.java
package com.pha.first.bean;
public class RecyclerBean {
String Desc;
public String getDesc() {
return Desc;
}
public void setDesc(String desc) {
Desc = desc;
}
}
与ListView比较:
ListView 有个自定义setBean()方法。但是只不过是ListView布局复杂,将复制过程提取放到Bean中 其他与ListView的bean类,并无不同。
5、准备明细数据
将每个明细itm的具体内容。
com/pha/first/RecyclerViewActivity.java 中新建方法InitData()方法,并在onCreate()调用该方法。
- 全局私有变量(数据存放的变量)
private List<RecyclerBean> rvData = new ArrayList<>();
- 定义InitData()方法
private void InitData() {
for(int i = 0;i < 120; i++){
RecyclerBean rvBean = new RecyclerBean();
if(i % 2 ==0){
rvBean.setDesc("上善若水,水利万物而不争,处众人之所恶,故几于道"+i);
}else{
rvBean.setDesc("居善地,心善渊,与善仁,言善信,正善治,事善能,动善时,夫唯不争,故无尤"+i);
}
rvData.add(rvBean);
}
}
6、新建Recycler适配器(视图和数据间的联系/桥梁)
- 新建 com/pha/first/adapter/RecyclerAdapter.java
- 继承 RecyclerView.Adapter,其中VH使用RecyclerAdapter.RecylerViewHolder,
格式:当前Adapter类名+ViewHolder(自定义,类似ListView中优化的ViewHolder ) - 继承RecyclerView.Adapter报错后,分别重写onCreateViewHolder()、onBindViewHolder()、getItemCount(),然后增加RecylerViewHolder()
- 定义数据rv_Data(界面需要数据的,数据类型就是List,RecylerBean就是刚才定义数据类)、context(视图,就是显示的容器界面视图)
- 构造函数RecyclerAdapter.java:
在RecyclerAdapter.java类里alt+insert(部分电脑需要fn+alt+insert) - 三个重写方法以及RecylerViewHolder修改
@NonNull
@Override
public RecylerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = View.inflate(context, R.layout.recyler_view_itm,null);
return new RecylerViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecylerViewHolder holder, int position) {
holder.tv_rv_itm_one.setText(rv_Data.get(position).getDesc());
}
@Override
public int getItemCount() {
return rv_Data == null? 0 : rv_Data.size();
}
public class RecylerViewHolder extends RecyclerView.ViewHolder {
private TextView tv_rv_itm_one;
public RecylerViewHolder(@NonNull View itemView) {
super(itemView);
tv_rv_itm_one = itemView.findViewById(R.id.tv_rv_itm_one);
}
}
- 添加RecyclerView明细的单击事件
RecyclerAdapter.java添加代码
已经修改练习代码顺序,看代码写的顺序,很容易理解这段含义
public interface OnRecylerViewItmClickListener{
void onRecylerViewItmClick(int position);
}
private OnRecylerViewItmClickListener mOnListener;
public void SetRecylerViewItmClickListener(OnRecylerViewItmClickListener onListener){
mOnListener=onListener;
}
适配器RecyclerAdapter.java最终代码
package com.pha.first.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.pha.first.R;
import com.pha.first.bean.RecyclerBean;
import java.util.List;
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.RecylerViewHolder> {
private List<RecyclerBean> rv_Data;
private Context context;
public RecyclerAdapter(List<RecyclerBean> rv_Data, Context context) {
this.rv_Data = rv_Data;
this.context = context;
}
@NonNull
@Override
public RecylerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = View.inflate(context, R.layout.recyler_view_itm,null);
return new RecylerViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecylerViewHolder holder, int position) {
holder.tv_rv_itm_one.setText(rv_Data.get(position).getDesc());
}
@Override
public int getItemCount() {
return rv_Data == null? 0 : rv_Data.size();
}
public class RecylerViewHolder extends RecyclerView.ViewHolder {
private TextView tv_rv_itm_one;
public RecylerViewHolder(@NonNull View itemView) {
super(itemView);
tv_rv_itm_one = itemView.findViewById(R.id.tv_rv_itm_one);
tv_rv_itm_one.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mOnListener != null){
mOnListener.onRecylerViewItmClick(getAdapterPosition());
}
}
});
}
}
public interface OnRecylerViewItmClickListener{
void onRecylerViewItmClick(int position);
}
private OnRecylerViewItmClickListener mOnListener;
public void SetRecylerViewItmClickListener(OnRecylerViewItmClickListener onListener){
mOnListener=onListener;
}
}
与ListView比较:
Adapter 是两个视图最大的差异,虽然差异答,但是大体思路差不多
onCreateViewHolder 返回视图
onBindViewHolder 绑定视图和数据
getItemCount 返回数据记录条数
RecylerViewHolder 就是ListView的ViewHolder
其中最大差异在于单击明细的监听事件
7、视图显示
在com/pha/first/RecyclerViewActivity.java 中新建方法ShowRecylerView方法,并在onCreate()调用该方法。
private void ShowRecylerView() {
RecyclerView recyclerView = findViewById(R.id.rv_one);
// 引用LinearLayout 布局 按行(一列) or 列(一行)对齐
// LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
// recyclerView.setLayoutManager(linearLayoutManager);
// 引用GridLayout 布局 按行 and 列 对齐
// GridLayoutManager gridLayoutManager = new GridLayoutManager(this,3);
// recyclerView.setLayoutManager(gridLayoutManager);
// 引用StaggerGridLayout 布局 按列对齐,可以错行;按行对齐,可以错列;
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3,LinearLayout.VERTICAL);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
RecyclerAdapter recylerAdapter = new RecyclerAdapter(rvData, this);
recyclerView.setAdapter(recylerAdapter);
recylerAdapter.SetRecylerViewItmClickListener(new RecyclerAdapter.OnRecylerViewItmClickListener() {
@Override
public void onRecylerViewItmClick(int position) {
Log.e(TAG, "onRecylerViewItmClick: "+rvData.get(position).getDesc() );
}
});
}
备注
这段代码中使用了三种方式、
- 引用LinearLayout 布局:
LinearLayoutManager 按行(一列) or 列(一行)对齐 - 引用GridLayout 布局:
GridLayoutManager 按行 and 列 对齐 - 引用StaggerGridLayout 布局:
StaggeredGridLayoutManager 按列对齐,可以错行;按行对齐,可以错列;
与ListView比较:
- ListView使用线性布局,不用单独设置布局。而RecyclerView 需要引用布局。
- ListView的明细单击事件在主界面ListView的id上,而RecyclerView 在recylerAdapter上,应为监听事件自定义在Adapter上
RecyclerViewActivity.java最终代码
package com.pha.first;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.LinearLayout;
import com.pha.first.adapter.RecyclerAdapter;
import com.pha.first.bean.RecyclerBean;
import java.util.ArrayList;
import java.util.List;
public class RecyclerViewActivity extends AppCompatActivity {
private static final String TAG = "RecylerLayout";
private List<RecyclerBean> rvData = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view);
// 数据初始化
InitData();
//显示RecylerView
ShowRecylerView();
}
private void ShowRecylerView() {
RecyclerView recyclerView = findViewById(R.id.rv_one);
// 引用LinearLayout 布局 按行(一列) or 列(一行)对齐
// LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
// recyclerView.setLayoutManager(linearLayoutManager);
// 引用GridLayout 布局 按行 and 列 对齐
// GridLayoutManager gridLayoutManager = new GridLayoutManager(this,3);
// recyclerView.setLayoutManager(gridLayoutManager);
// 引用StaggerGridLayout 布局 按列对齐,可以错行;按行对齐,可以错列;
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3,LinearLayout.VERTICAL);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
RecyclerAdapter recylerAdapter = new RecyclerAdapter(rvData, this);
recyclerView.setAdapter(recylerAdapter);
recylerAdapter.SetRecylerViewItmClickListener(new RecyclerAdapter.OnRecylerViewItmClickListener() {
@Override
public void onRecylerViewItmClick(int position) {
Log.e(TAG, "onRecylerViewItmClick: "+rvData.get(position).getDesc() );
}
});
}
private void InitData() {
for(int i = 0;i < 120; i++){
RecyclerBean rvBean = new RecyclerBean();
if(i % 2 ==0){
rvBean.setDesc("上善若水,水利万物而不争,处众人之所恶,故几于道"+i);
}else{
rvBean.setDesc("居善地,心善渊,与善仁,言善信,正善治,事善能,动善时,夫唯不争,故无尤"+i);
}
rvData.add(rvBean);
}
}
}
效果图
这是StaggerGridLayout 布局的效果入,至于其他的两种视图,自己动手试一下吧。。。