Android - 强大的RecyclerView

Posted 小柴的回忆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android - 强大的RecyclerView相关的知识,希望对你有一定的参考价值。

强大的RecyclerView

RecyclerView是androidx库的控件,低版本可能需要自行导入,但现在的版本是默认加上的
RecyclerView是一个强大的控件,主要用于替代ListView,ListView能实现的功能,他也能实现,他比ListView更好用,更方面,功能更加全面。

一、RecyclerView的使用主要涉及3个类:RecyclerView、Adapter,和ViewHolder

1.RecyclerView类

RecyclerView是ViewGroup的子类,每一个列表项都是作为一个View子对象显示的。这些
View子对象可简单可复杂,这取决于列表项要显示些什么。
RecyclerView顾名思义回收视图,他的一大特点就是回收,他只会显示屏幕能显示的几个布局,当滑动的时候,会将不要的视图回收,然后显示新的视图。而RecyclerView的任务仅仅只是回收和定位屏幕上的View,其余的功能都是交给Adapter和ViewHolder处理

2.ViewHolder

而ViewHolder所做的任务更少,就只有一个,就是用于容纳View视图,因为RecyclerView不会创建视图,所以视图都是ViewHolder创建的

3.Adapter

而上面的ViewHolder是由Adapter创建的,同时他是一个控制器,控制着RecyclerView。先创建好ViewHolder,绑定ViewHolder至模型层,然后从模型层取出数据,提供给RecyclerView显示

4.RecyclerView直接定位最后一个item

recyclerView.scrollToPosition(msgList.size - 1) ,直接定位到最后一个item

二、RecyclerView的使用

简单的吹完RecyclerView的理论,那就开始使用吧
这里我将RecyclerView用于显示学生数据

1.创建一个Student类

里面有4个数据,头像图片,名字,成绩与自我介绍

class Student(val name : String, val grade : Int, val headerImg : Int, val sign : String) 

2.创建一个item的视图

也就是列表中一项的视图
这里采用的是ConstraintLayout约束布局,不懂的小伙伴点这里 ↓
约束布局ConstraintLayout看这一篇就够了

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ImageView
        android:id="@+id/header"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_margin="5dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>
    <TextView
        android:id="@+id/name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        app:layout_constraintRight_toLeftOf="@id/barrier"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@id/header"/>
    <TextView
        android:id="@+id/sign"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:textSize="12sp"
        app:layout_constraintLeft_toRightOf="@id/header"
        app:layout_constraintRight_toLeftOf="@id/barrier"
        app:layout_constraintTop_toBottomOf="@id/name"/>

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        app:barrierDirection="end"
        app:constraint_referenced_ids="name, sign"/>
    <TextView
        android:id="@+id/grade"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        app:layout_constraintLeft_toRightOf="@id/barrier"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>


</androidx.constraintlayout.widget.ConstraintLayout>

3.随便找几张图片作为头像

4.创建一个StudentAdapter适配器与ViewHolder

//创建一个StudentAdapter,构造函数传入一个Student列表数据,
// 同时继承RecyclerView.Adapter<>类,传入的泛型类是继承ViewHolder的类,所以下面的ViewHolder符合
class StudentAdapter(private val context : Context, private val studentList: List<Student>) : RecyclerView.Adapter<StudentAdapter.ViewHolder>() 
    //该类是继承RecyclerView的内部类ViewHolder
    //这里传入的view,通常都是一个item的最外部类,也就是上面创建的xml文件,用于获取该item中的所有控件实例
    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) 
        val studentHeader : ImageView = view.findViewById(R.id.header)
        val studentName : TextView = view.findViewById(R.id.name)
        val studentSign : TextView = view.findViewById(R.id.sign)
        val studentGrade : TextView = view.findViewById(R.id.grade)
    

    //看方法名就知道,这是用于创建ViewHolder实例的,同时将实例返回
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder 
        //创建视图
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_student, parent, false)
        return ViewHolder(view)
    

    //用于对item进行数据赋值
    override fun onBindViewHolder(holder: ViewHolder, position: Int) 
        val student = studentList[position]
        holder.studentHeader.setImageResource(student.headerImg)
        holder.studentName.text = student.name
        holder.studentSign.text = student.sign
        holder.studentGrade.text = "等级:$student.grade"
        holder.studentGrade.setOnClickListener //添加了一个点击成绩的点击事件,用于弹出一个Toast
            Toast.makeText(context, "$student.name同学的等级是:$student.grade", Toast.LENGTH_SHORT).show()
        
    

    //用于告诉RecyclerView一共有多少个item
    override fun getItemCount() = studentList.size

5.设置Activity的布局

创建好了RecyclerView要使用的内容, 就要创建一个RecyclerView了
修改activity_main布局,里面就只有一个占满全屏的RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity : AppCompatActivity() 
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val recyclerView : RecyclerView = findViewById(R.id.list) //获取recyclerView实例
        val layoutManager = LinearLayoutManager(this) //获取线性布局管理实例
        recyclerView.layoutManager = layoutManager //设置recyclerView的布局管理为线性布局管理
        val studentList : ArrayList<Student> = init() //创建一个学生列表
        val adapter = StudentAdapter(this, studentList) //创建一个StudentAdapter
        recyclerView.adapter = adapter //设置recyclerView的适配器为StudentAdapter的适配器

    

    //获取一个学生列表
    fun init() : ArrayList<Student>
        val students = ArrayList<Student>()
        var i = 1
        repeat(100)
            val resource = when  //主要用户显示不同的头像,嘿嘿
                i % 3 == 0 -> 
                    R.drawable.header1
                
                i % 3 == 1 -> 
                    R.drawable.header2
                
                else -> 
                    R.drawable.header3
                
            
            students.add(Student("我是刘同学$i号", (1..10).random(), resource, "我就是我,我就是刘同学"))
            i += 1
        
        return students
    

这就大功告成了,一个简单的列表实现了

6.水平方向布局

主要是修改recyclerView.layoutManager = 布局管理
水平方向最简单,只需要修改这里既可

 val layoutManager = LinearLayoutManager(this) //获取线性布局管理实例
 layoutManager.orientation = LinearLayoutManager.HORIZONTAL
 recyclerView.layoutManager = layoutManager //设置recyclerView的布局管理为线性布局管理

修改item_student

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ImageView
        android:id="@+id/header"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_margin="5dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <TextView
        android:id="@+id/grade"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        app:layout_constraintLeft_toRightOf="@id/header"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
    <TextView
        android:id="@+id/name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        app:layout_constraintTop_toBottomOf="@id/header"
        app:layout_constraintLeft_toLeftOf="parent"/>
    <TextView
        android:id="@+id/sign"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:textSize="12sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/name"/>

</androidx.constraintlayout.widget.ConstraintLayout>

7.瀑布流布局

val layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) //获取瀑布流布局管理实例
recyclerView.layoutManager = layoutManager //设置recyclerView的布局管理为瀑布流布局管理

item_student布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ImageView
        android:id="@+id/header"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_margin="5dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <TextView
        android:id="@+id/grade"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        app:layout_constraintLeft_toRightOf="@id/header"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
    <TextView
        android:id="@+id/name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        app:layout_constraintTop_toBottomOf="@id/header"
        app:layout_constraintLeft_toLeftOf="parent"/>
    <TextView
        android:id="@+id/sign"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:textSize="12sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/name"/>

</androidx.constraintlayout.widget.ConstraintLayout>

三、多item布局

我们上面的内容都是单item布局,什么意思呢,就是所有的数据都是使用同一个item的视图
而多item布局是可以使用多个不通的item布局,这里我们就使用左右不同的视图来区分
而我这里就简单举例,所以只用了不同的颜色背景与不同的布局来区分

1.设置左右item布局

首先是item_left_student

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/teal_200"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ImageView
        android:id="@+id/header"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_margin="5dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <TextView
        android:id="@+id/grade"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        app:layout_constraintLeft_toRightOf="@id/header"
        app:layou

以上是关于Android - 强大的RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章

Android - 强大的RecyclerView

Android - 强大的RecyclerView

Android可伸缩布局-FlexboxLayout(支持RecyclerView集成)

Android之RecyclerView介绍

RecyclerView

从0系统学Android--3.6 RecyclerView