Android基础进阶 - RecyclerView列表加载多类型视图

你是否会经常见到在同一个 RecyclerView 列表中加载多种不同的布局效果?最近写了一篇 ConcatAdapter 相关内容,发现虽然之前一直在使用多类型视图列表,但从未记录过,故重新记录于此

RecyclerView基础

RecyclerView扩展

RecyclerView相关功能

那年花开

实现效果 (不同背景色代表不同 ViewType 视图)

前置要求

包含数据结构视图结构

前置结构

问:在列表中你如何判断某条数据加载对应视图?

答:不论如何,数据结构中一定有一个类似type的字段用于区分展示哪种类型的视图

kotlin 复制代码
package com.example.concatadatper

class MoreTypeBean(var data: String, var type: Int)

前置视图

列表中有几种视图类型,一般就意味着有几种对应的 layout布局ViewHolder

Tip

  • 为了更直观查看实现效果,简化了视图类型对应的 layout 布局
  • 当前不同类型的ViewHolder写在了Adapter中,如有需求也可以抽出来

item_first (视图类型一)

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="50dp"
    android:orientation="vertical">

    <TextView
        android: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 复制代码
<?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">

    <TextView
        android: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,通过重写内部 onCreateViewHolderonBindViewHoldergetItemViewType方法,从而加载不同的视图,处理不同的逻辑,具体如下

kotlin 复制代码
package com.example.concatadatper

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class MoreViewAdapter(private val dataList: MutableList<MoreTypeBean>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private val FIRST_TYPE = 1
    private val SECOND_TYPE = 2

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        //根据不同itemType加载不同的ViewHolder
        return 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: TextView

        init {
            firstText = itemView.findViewById<TextView>(R.id.tv_first)
        }
    }

    /**
     * 第二种视图类型
     * */
    class SecondViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var secondText: TextView

        init {
            secondText = itemView.findViewById<TextView>(R.id.tv_second)
        }
    }
}

使用方式

kotlin 复制代码
package com.example.concatadatper

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class 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 复制代码
<?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.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</androidx.appcompat.widget.LinearLayoutCompat>
相关推荐
fatiaozhang952717 分钟前
中兴云电脑W102D_晶晨S905X2_2+16G_mt7661无线_安卓9.0_线刷固件包
android·adb·电视盒子·魔百盒刷机·魔百盒固件
CYRUS_STUDIO1 小时前
Android APP 热修复原理
android·app·hotfix
鸿蒙布道师2 小时前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师2 小时前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
大耳猫2 小时前
【解决】Android Gradle Sync 报错 Could not read workspace metadata
android·gradle·android studio
ta叫我小白2 小时前
实现 Android 图片信息获取和 EXIF 坐标解析
android·exif·经纬度
dpxiaolong3 小时前
RK3588平台用v4l工具调试USB摄像头实践(亮度,饱和度,对比度,色相等)
android·windows
tangweiguo030519874 小时前
Android 混合开发实战:统一 View 与 Compose 的浅色/深色主题方案
android
老狼孩111225 小时前
2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发
android·机器人·自动化·lua·脚本开发·懒人精灵·免root开发
打死不学Java代码5 小时前
PaginationInnerInterceptor使用(Mybatis-plus分页)
android·java·mybatis