如何使用单个RecyclerView展示多模型类的结构化数据?
嘿,这事儿我熟!要在单个RecyclerView里展示这种分模块、多数据类型的内容,核心思路就是用多类型ItemView来处理不同模块的标题和数据。我给你一步步拆解实现方法:
1. 定义对应的数据模型类
首先给每个模块(包括标题栏)创建专属的模型类,这样能清晰区分不同类型的数据:
// 用于模块标题的模型(比如「教育模块」这种标题项) data class SectionModel(val title: String) // 教育模块的数据模型 data class EducationModel(val degree: String) // 工作经历模块的数据模型 data class WorkExperienceModel(val companyName: String) // 参考人模块的数据模型 data class ReferenceModel(val personName: String) // 附件模块的数据模型 data class AttachmentModel(val documentName: String)
2. 创建不同类型的ViewHolder
每个数据类型对应一个ViewHolder,负责绑定对应的布局控件:
// 标题栏ViewHolder class SectionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val titleTv: TextView = itemView.findViewById(R.id.tv_section_title) } // 教育项ViewHolder class EducationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val degreeTv: TextView = itemView.findViewById(R.id.tv_degree) } // 工作经历项ViewHolder class WorkExperienceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val companyTv: TextView = itemView.findViewById(R.id.tv_company) } // 参考人项ViewHolder class ReferenceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val personTv: TextView = itemView.findViewById(R.id.tv_person) } // 附件项ViewHolder class AttachmentViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val documentTv: TextView = itemView.findViewById(R.id.tv_document) }
3. 编写多类型Adapter
这是核心部分,我们需要通过getItemViewType区分不同的Item类型,然后在创建和绑定ViewHolder时做对应的处理:
class MultiTypeAdapter(private val itemList: List<Any>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { // 定义不同Item的类型标识 companion object { private const val TYPE_SECTION = 0 private const val TYPE_EDUCATION = 1 private const val TYPE_WORK_EXPERIENCE = 2 private const val TYPE_REFERENCE = 3 private const val TYPE_ATTACHMENT = 4 } // 返回当前Item的类型 override fun getItemViewType(position: Int): Int { return when (itemList[position]) { is SectionModel -> TYPE_SECTION is EducationModel -> TYPE_EDUCATION is WorkExperienceModel -> TYPE_WORK_EXPERIENCE is ReferenceModel -> TYPE_REFERENCE is AttachmentModel -> TYPE_ATTACHMENT else -> throw IllegalArgumentException("遇到未知的Item类型啦!") } } // 根据类型创建对应的ViewHolder override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val inflater = LayoutInflater.from(parent.context) return when (viewType) { TYPE_SECTION -> { val view = inflater.inflate(R.layout.item_section_title, parent, false) SectionViewHolder(view) } TYPE_EDUCATION -> { val view = inflater.inflate(R.layout.item_education, parent, false) EducationViewHolder(view) } TYPE_WORK_EXPERIENCE -> { val view = inflater.inflate(R.layout.item_work_experience, parent, false) WorkExperienceViewHolder(view) } TYPE_REFERENCE -> { val view = inflater.inflate(R.layout.item_reference, parent, false) ReferenceViewHolder(view) } TYPE_ATTACHMENT -> { val view = inflater.inflate(R.layout.item_attachment, parent, false) AttachmentViewHolder(view) } else -> throw IllegalArgumentException("遇到未知的View类型啦!") } } // 根据类型绑定对应的数据 override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { val item = itemList[position] when (holder) { is SectionViewHolder -> { val section = item as SectionModel holder.titleTv.text = section.title } is EducationViewHolder -> { val education = item as EducationModel holder.degreeTv.text = "*${education.degree}" // 按照需求给学位加强调格式 } is WorkExperienceViewHolder -> { val work = item as WorkExperienceModel holder.companyTv.text = work.companyName } is ReferenceViewHolder -> { val reference = item as ReferenceModel holder.personTv.text = reference.personName } is AttachmentViewHolder -> { val attachment = item as AttachmentModel holder.documentTv.text = attachment.documentName } } } override fun getItemCount(): Int = itemList.size }
4. 准备布局文件
给每个ViewHolder对应创建布局文件,举几个简单例子:
模块标题布局(item_section_title.xml)
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv_section_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:textSize="18sp" android:textStyle="bold" android:background="#f0f0f0"/>
教育项布局(item_education.xml)
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv_degree" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingHorizontal="16dp" android:paddingVertical="8dp" android:textSize="16sp"/>
其他模块的布局可以参照这个逻辑来写,只要对应好ViewHolder里的控件ID就行。
5. 组装数据并设置RecyclerView
最后把各个模块的标题和数据合并成一个总列表,然后给RecyclerView设置Adapter:
// 准备各个模块的数据源 val educationList = listOf( EducationModel("10年级"), EducationModel("12年级(理科)"), EducationModel("计算机学士") ) val workExperienceList = listOf( WorkExperienceModel("公司2"), WorkExperienceModel("公司3") ) val referenceList = listOf( ReferenceModel("X先生"), ReferenceModel("Y先生"), ReferenceModel("Z先生") ) val attachmentList = listOf( AttachmentModel("文档1"), AttachmentModel("文档2"), AttachmentModel("文档3") ) // 把模块标题和对应数据合并成一个总列表 val combinedList = mutableListOf<Any>().apply { add(SectionModel("教育模块")) addAll(educationList) add(SectionModel("工作经历模块")) addAll(workExperienceList) add(SectionModel("参考人模块")) addAll(referenceList) add(SectionModel("附件模块")) addAll(attachmentList) } // 初始化RecyclerView val recyclerView = findViewById<RecyclerView>(R.id.recyclerView) recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = MultiTypeAdapter(combinedList)
这样就能在单个RecyclerView里完美展示你需要的分模块内容啦,不同模型类的ArrayList也能被统一处理~
内容的提问来源于stack exchange,提问作者Prachi Karapurkar
相关产品推荐
相关产品推荐

