使用RecyclerView 可以实现ListView(列表), GridView(网格),StaggeredView(瀑布流)的效果,
并且可以自动回收没有使用的条目。
使用RecyclerView的方法,可以总结如下:
目录
4.1 继承 RecyclerView.Adapter 并且实现 泛型 RecyclerView.ViewHolder
4.3 重写获取条目数目、创建ViewHolder、绑定ViewHolder的方法
1. 布局文件使用RecyclerView: activity_main.xml
<?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="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
其中需要在app 的build.gradle中添加RecyclerView包的依赖(不同SDK版本, 会有些许差异):
dependencies {
//此处省略其它的配置
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
2. 创建RecyclerView的条目 : item_list_view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="90dp">
<androidx.cardview.widget.CardView
app:cardUseCompatPadding="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/user_image"
android:layout_width="60dp"
android:layout_height="70dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:scaleType="fitCenter"
android:src="@drawable/pic1" />
<TextView
android:id="@+id/user_name"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginTop="20dp"
android:layout_marginLeft="15dp"
android:layout_toRightOf="@id/user_image"
android:text="User Name1" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
其中CardView 只是起到添加边框的作用,使得看起来稍微好看的,装饰作用,
需要在app 的build.gradle中添加依赖
//此处省略其它
implementation 'androidx.cardview:cardview:1.0.0'
3. 定义条目的使用的数据:
UserData, 一个String 类型的名字, 一个对应的图片(Int 类型的id)
package com.example.androidrecyclerviewtest.data
class UserData {
var userName: String
var userImageId: Int
constructor(userNameId: String, userImageId: Int) {
this.userName = userNameId
this.userImageId = userImageId
}
}
其中,名字和图片的资源定义在一个常量类中,方便管理:
pic1~pic12 为图片,可以随意加到drawable资源文件+下,
user_name1 ~user_name12 为名字,可以随意加到strings.xml 中
object CommonConstants {
val PIC_IDS = mutableListOf(
R.drawable.pic1,
R.drawable.pic2,
R.drawable.pic3,
R.drawable.pic4,
R.drawable.pic5,
R.drawable.pic6,
R.drawable.pic7,
R.drawable.pic8,
R.drawable.pic9,
R.drawable.pic10,
R.drawable.pic11,
R.drawable.pic12
)
val USER_NAMES = mutableListOf(
R.string.user_name1,
R.string.user_name2,
R.string.user_name3,
R.string.user_name4,
R.string.user_name5,
R.string.user_name6,
R.string.user_name7,
R.string.user_name8,
R.string.user_name9,
R.string.user_name10,
R.string.user_name11,
R.string.user_name12
)
}
4. 创建适配器Adapter (关键)
适配器决定了如何把数据映射到条目上显示。
4.1 继承 RecyclerView.Adapter 并且实现 泛型 RecyclerView.ViewHolder
ViewHolder 可以理解为每个条目的显示缓存,是Adpater的关键
class ListViewAdpater :
RecyclerView.Adapter<ListViewAdpater.InnerViewHolder> {
class InnerViewHolder : RecyclerView.ViewHolder {
//此处暂未实现
}
}
4.2 构造函数参数传入数据,并使用成员变量保存
private var datas: MutableList<UserData>
// 1. 适配器持有数据的引用
constructor(datas: MutableList<UserData>) {
this.datas = datas
}
4.3 重写获取条目数目、创建ViewHolder、绑定ViewHolder的方法
override fun getItemCount(): Int {
return if (datas != null) {
datas.size
} else {
0
}
}
//2. 创建条目 - 每个条目只会创建一次,后续刷新到仅调用 onBinderViewHolder 进行数据绑定
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): InnerViewHolder {
val view = View.inflate(parent.context,R.layout.item_list_view, null)
return InnerViewHolder(view)
}
//3. 绑定数据 - position 对应数据的下标号 - 数据可以变化,只要数据数目不增加,条目也不会增加
override fun onBindViewHolder(holder: InnerViewHolder, position: Int) {
holder.setData(datas[position])
}
如果要设置
点击Item时响应
,最好是在这里添加监听器(自定义个接口用于回调)。 如果是在
ViewHolder中添加监听
,那么回调中用到的数据可能是
创建ViewHolder时的数据,
并不是
当前绑定的数据
。
此时,需要实现InnerViewHolder的内部操作,即把数据设置到条目上 (ItemView 为传入的条目)
class InnerViewHolder : RecyclerView.ViewHolder {
private var image: ImageView
private var nameText: TextView
constructor(itemView: View) : super(itemView) {
this.nameText = itemView.user_name
this.image = itemView.user_image
}
fun setData(userData: UserData) {
nameText.text = userData.userName
image.setImageResource(userData.userImageId)
}
}
5. Activity 3部曲
在Activity 加载包含有recyclerview控件的布局文件
setContentView(R.layout.activity_main)
5.1 初始化数据
private var datas = mutableListOf<UserData>()
private fun initDatas() {
for (index in 0 until USER_NAMES.size) {
datas.add(
index,
UserData(
context.getString(USER_NAMES[index]), PIC_IDS[index]
)
)
}
}
5.2 设置布局管理器
//2. 创建并设置布局管理器
var layoutManager = LinearLayoutManager(context)
layoutManager.orientation = LinearLayoutManager.VERTICAL
recycler_view.layoutManager = layoutManager
5.3 设置适配器
//3. 创建并设置adapter
adapter=
ListViewAdpater(datas)
recycler_view.adapter = adapter
虽然很简单,但是在实际操作一遍后,可以加深理解。
这些只是基本操作, 后续会再更新显示不同类型的条目,下拉和上拉刷新等