欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Android学习笔记】RecyclerView的用法

程序员文章站 2022-06-14 11:05:05
...

介绍

由于ListView存在各种不足并且无法实现横向滚动,Android提供了一个更强大的滚动组件——RecyclerView,不仅可以轻松实现和ListView同样的效果,还优化了ListView中存在的各种不足之处。

基本用法

创建一个工程RecyclerViewTestProject,首先需要为项目添加RecyclerView相应的依赖库,修改app/build.gradle文件中的dependencies闭包如下:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

然后修改MainActivity对应的布局文件:

<?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/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</LinearLayout>

接着定义一个实体类,作为RecyclerView适配器的适配类型,新建类Model如下:

package com.example.recyclerviewtestproject;

public class Model {

    private String leftString;
    private String rightString;

    public String getLeftString() {
        return leftString;
    }

    public void setLeftString(String leftString) {
        this.leftString = leftString;
    }

    public String getRightString() {
        return rightString;
    }

    public void setRightString(String rightString) {
        this.rightString = rightString;
    }
}

然后为RecyclerView指定一个我们自定义的布局,新建布局文件model_item.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:orientation="horizontal"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
    >

    <TextView
        android:id="@+id/left_text"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center_vertical|left"
        />

    <TextView
        android:id="@+id/right_text"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center_vertical|right"
        />

</LinearLayout>

到了这里,咱们需要为RecyclerView准备一个适配器,新建ModelAdapter类,内容如下:

package com.example.recyclerviewtestproject;

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;

public class ModelAdapter extends RecyclerView.Adapter<ModelAdapter.ViewHolder> {

    private List<Model> modelList;

    static class ViewHolder extends RecyclerView.ViewHolder{
        TextView leftTextView,rightTextView;

        public ViewHolder(View view) {
            super(view);
            leftTextView = view.findViewById(R.id.left_text);
            rightTextView = view.findViewById(R.id.right_text);
        }
    }

    public ModelAdapter(List<Model> modelList){
        this.modelList = modelList;
    }

    //创建ViewHolder实例并返回
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.model_item,parent,false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    //对RecyclerView子项数据进行赋值,会在每个子项被滚动到屏幕内的时候执行
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Model model = modelList.get(position);
        holder.leftTextView.setText(model.getLeftString());
        holder.rightTextView.setText(model.getRightString());
    }

    @Override
    public int getItemCount() {
        return modelList.size();
    }

}

适配器准备好之后,咱们就可以开始使用RecyclerView了,修改MainActivity代码如下:

package com.example.recyclerviewtestproject;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<Model> modelList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();//初始化数据
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        ModelAdapter adapter = new ModelAdapter(modelList);
        recyclerView.setAdapter(adapter);
    }

    private void initData(){
        for(int i='a';i<='z';i++){
            String leftString = ""+(char)i+(char)i+(char)i;
            String rightString = ""+(char)(i-32)+(char)(i-32)+(char)(i-32);
            Model model = new Model();
            model.setLeftString(leftString);
            model.setRightString(rightString);
            modelList.add(model);
        }
    }
}

运行APP,发现效果已实现:

【Android学习笔记】RecyclerView的用法

实现横向滚动

首先要对model_item.xml进行修改,布局方向修改为竖直方向,宽度统一为80dp,并对TextView进行相应的修改:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="80dp"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
    >

    <TextView
        android:id="@+id/left_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        />

    <TextView
        android:id="@+id/right_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        />

</LinearLayout>

 修改完之后,原来的left_text就变成了上面的文本,原来的right_text就变成了下面的文本。

接着修改MainActivity中的代码,设置布局为横向排列:

package com.example.recyclerviewtestproject;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<Model> modelList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();//初始化数据
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);//设置布局为横向排列
        recyclerView.setLayoutManager(layoutManager);
        ModelAdapter adapter = new ModelAdapter(modelList);
        recyclerView.setAdapter(adapter);
    }

    private void initData(){
        for(int i='a';i<='z';i++){
            String leftString = ""+(char)i+(char)i+(char)i;
            String rightString = ""+(char)(i-32)+(char)(i-32)+(char)(i-32);
            Model model = new Model();
            model.setLeftString(leftString);
            model.setRightString(rightString);
            modelList.add(model);
        }
    }
}

运行APP,效果如下:

【Android学习笔记】RecyclerView的用法

实现瀑布流布局

使用StaggeredGridLayoutManager可以实现瀑布流布局。

由于瀑布流宽度是由布局的列数来自动适配的,直接让layout_width属性值为match_parent即可;修改Layout_margin属性值为5dp,让子项间保留空隙;修改model_item.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:orientation="vertical"
    android:layout_margin="5dp"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
    >

    <TextView
        android:id="@+id/left_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        />

    <TextView
        android:id="@+id/right_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="left"
        />

</LinearLayout>

然后修改MainActivity代码,让right_text的长度随机,这里我想让它变为4列瀑布流,使用如下代码就可以了:

package com.example.recyclerviewtestproject;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import android.os.Bundle;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    private List<Model> modelList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();//初始化数据
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        //参数1:布局的列数;参数2:布局的排列方向
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);
        ModelAdapter adapter = new ModelAdapter(modelList);
        recyclerView.setAdapter(adapter);
    }

    private void initData(){
        for(int i='a';i<='z';i++){
            String leftString = ""+(char)i+(char)i+(char)i;
            String s = ""+(char)(i-32)+(char)(i-32)+(char)(i-32);
            String rightString = getRandomText(s);
            Model model = new Model();
            model.setLeftString(leftString);
            model.setRightString(rightString);
            modelList.add(model);
        }
    }

    //生成随机长度字符串
    private String getRandomText(String s){
        Random random = new Random();
        int num = random.nextInt(20)+21;
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<num;i++){
            sb.append(s);
        }
        return sb.toString();
    }

}

运行APP,效果如下:

【Android学习笔记】RecyclerView的用法

 实现网格布局

在瀑布流的基础代码上,只需要修改MainActivity代码如下就可以了:

package com.example.recyclerviewtestproject;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import android.os.Bundle;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    private List<Model> modelList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();//初始化数据
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        //参数1:Context变量;参数2:网格布局的行列数
        GridLayoutManager layoutManager = new GridLayoutManager(this,3);
        recyclerView.setLayoutManager(layoutManager);
        ModelAdapter adapter = new ModelAdapter(modelList);
        recyclerView.setAdapter(adapter);
    }

    private void initData(){
        for(int i='a';i<='z';i++){
            String leftString = ""+(char)i+(char)i+(char)i;
            String s = ""+(char)(i-32)+(char)(i-32)+(char)(i-32);
            String rightString = getRandomText(s);
            Model model = new Model();
            model.setLeftString(leftString);
            model.setRightString(rightString);
            modelList.add(model);
        }
    }

    //生成随机长度字符串
    private String getRandomText(String s){
        Random random = new Random();
        int num = random.nextInt(20)+21;
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<num;i++){
            sb.append(s);
        }
        return sb.toString();
    }

}

运行APP效果如下:

【Android学习笔记】RecyclerView的用法

可以看到,每一行的三个元素,高度是一致的,具体高度取决于高度最高的元素。

RecyclerView的点击事件

RecyclerView的点击事件实现起来比ListView更复杂,所有的点击事件都是由具体的View去注册。

现在咱们尝试下为RecyclerView注册点击事件,修改ModelAdapter代码如下:

package com.example.recyclerviewtestproject;

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 ModelAdapter extends RecyclerView.Adapter<ModelAdapter.ViewHolder> {

    private List<Model> modelList;

    static class ViewHolder extends RecyclerView.ViewHolder{
        View modelView;//新增
        TextView leftTextView,rightTextView;

        public ViewHolder(View view) {
            super(view);
            modelView = view;//新增
            leftTextView = view.findViewById(R.id.left_text);
            rightTextView = view.findViewById(R.id.right_text);
        }
    }

    public ModelAdapter(List<Model> modelList){
        this.modelList = modelList;
    }

    //创建ViewHolder实例并返回
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.model_item,parent,false);
        final ViewHolder holder = new ViewHolder(view);
        //为子项整体添加点击事件
        holder.modelView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int position = holder.getAdapterPosition();
                Model model = modelList.get(position);
                Toast.makeText(view.getContext(),"you clicked big view "+model.getRightString(),Toast.LENGTH_SHORT).show();
            }
        });
        //为子项中的控件添加点击事件
        holder.leftTextView.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                int position = holder.getAdapterPosition();
                Model model = modelList.get(position);
                Toast.makeText(view.getContext(),"you clicked view "+model.getLeftString(),Toast.LENGTH_SHORT).show();
            }
        });
        //为子项中的控件添加点击事件
        holder.rightTextView.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                int position = holder.getAdapterPosition();
                Model model = modelList.get(position);
                Toast.makeText(view.getContext(),"you clicked view "+model.getRightString(),Toast.LENGTH_SHORT).show();
            }
        });

        return holder;
    }

    //对RecyclerView子项数据进行赋值,会在每个子项被滚动到屏幕内的时候执行
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Model model = modelList.get(position);
        holder.leftTextView.setText(model.getLeftString());
        holder.rightTextView.setText(model.getRightString());
    }

    @Override
    public int getItemCount() {
        return modelList.size();
    }

}

运行APP,效果如下:

【Android学习笔记】RecyclerView的用法