你是否会经常见到在同一个 RecyclerView 列表中加载多种不同的布局效果?最近写了一篇 ConcatAdapter 相关内容,发现虽然之前一直在使用多类型视图列表,但从未记录过,故重新记录于此
RecyclerView基础
- Android进阶之路 - RecyclerView基础使用(17年)
- Android进阶之路 - RecyclerView实现横、纵向滑动列表(19年)
RecyclerView相关功能
- Android进阶之路 - RecyclerView左划删除(SwipeRecyclerView的简单使用 17年)
- Android进阶之路 - RecyclerView列表置顶、滑动到指定条目(18年)
- Android进阶之路 - RecyclerView列表自动无限水平滚动(21年)
- Android进阶之路 - 双列表联动效果(18年)
那年花开
- 前置要求
- 前置结构
- 前置视图
- 核心实现
- 使用方式
实现效果(不同背景色代表不同 ViewType
视图)
前置要求
包含数据结构
、视图结构
前置结构
问:在列表中你如何判断某条数据加载对应视图?
答:不论如何,数据结构中一定有一个类似type的字段用于区分展示哪种类型的视图
package com.example.concatadatperclass MoreTypeBean(var data: String, var type: Int)
前置视图
列表中有几种视图类型,一般就意味着有几种对应的
layout布局
和ViewHolder
Tip
- 为了更直观查看实现效果,简化了视图类型对应的
layout
布局 - 当前不同类型的
ViewHolder
写在了Adapter
中,如有需求也可以抽出来
item_first (视图类型一)
<?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="50dp"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:background="#f65478"android:textColor="#ffffff"android:id="@+id/tv_first"android:text="First" />
</LinearLayout>
item_second(视图类型二)
<?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="50dp"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:background="#e98745"android:textColor="#ffffff"android:id="@+id/tv_second"android:text="Second" />
</LinearLayout>
核心实现
常规的多类型视图列表, RecyclerView
一般只有一个 Adapter
,通过重写内部 onCreateViewHolder
、onBindViewHolder
、getItemViewType
方法,从而加载不同的视图,处理不同的逻辑,具体如下
package com.example.concatadatperimport android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerViewclass MoreViewAdapter(private val dataList: MutableList<MoreTypeBean>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {private val FIRST_TYPE = 1private val SECOND_TYPE = 2override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {//根据不同itemType加载不同的ViewHolderreturn if (viewType == FIRST_TYPE) {val firstView = LayoutInflater.from(parent.context).inflate(R.layout.item_first, parent, false)FirstViewHolder(firstView)} else {val secondView = LayoutInflater.from(parent.context).inflate(R.layout.item_second, parent, false)SecondViewHolder(secondView)}}override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {//不同的视图类型,逻辑也有所不同val currentInfo = dataList[position]if (currentInfo.type == FIRST_TYPE) {(holder as FirstViewHolder).firstText.text = currentInfo.data} else {(holder as SecondViewHolder).secondText.text = currentInfo.data}}override fun getItemCount(): Int {return dataList.size}/*** Tip:记得重写该处逻辑,否则onCreateViewHolder返回可能有问题* */override fun getItemViewType(position: Int): Int {return dataList[position].type}/*** 第一种视图类型* */class FirstViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {var firstText: TextViewinit {firstText = itemView.findViewById<TextView>(R.id.tv_first)}}/*** 第二种视图类型* */class SecondViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {var secondText: TextViewinit {secondText = itemView.findViewById<TextView>(R.id.tv_second)}}
}
使用方式
package com.example.concatadatperimport android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerViewclass MainActivity : AppCompatActivity() {private var totalList: MutableList<MoreTypeBean> = mutableListOf<MoreTypeBean>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)//数据模拟(当前有1、2俩种类型,对应的背景色)totalList.add(MoreTypeBean("窗前明月光", 1))totalList.add(MoreTypeBean("昨日已熬夜", 2))totalList.add(MoreTypeBean("老夫思故乡", 1))totalList.add(MoreTypeBean("今日又熬夜", 2))totalList.add(MoreTypeBean("明日得早睡", 2))//视图关联val mRv = findViewById<RecyclerView>(R.id.rv)val moreViewAdapter = MoreViewAdapter(totalList)mRv.layoutManager = LinearLayoutManager(this)mRv.adapter = moreViewAdapter}
}
activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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.RecyclerViewandroid:id="@+id/rv"android:layout_width="match_parent"android:layout_height="match_parent" />
</androidx.appcompat.widget.LinearLayoutCompat>