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>
相关推荐
Good_tea_h2 小时前
Android中的单例模式
android·单例模式
计算机源码社6 小时前
分享一个基于微信小程序的居家养老服务小程序 养老服务预约安卓app uniapp(源码、调试、LW、开题、PPT)
android·微信小程序·uni-app·毕业设计项目·毕业设计源码·计算机课程设计·计算机毕业设计开题
丶白泽7 小时前
重修设计模式-结构型-门面模式
android
晨春计8 小时前
【git】
android·linux·git
标标大人9 小时前
c语言中的局部跳转以及全局跳转
android·c语言·开发语言
竹林海中敲代码9 小时前
Qt安卓开发连接手机调试(红米K60为例)
android·qt·智能手机
木鬼与槐10 小时前
MySQL高阶1783-大满贯数量
android·数据库·mysql
iofomo10 小时前
【Abyss】Android 平台应用级系统调用拦截框架
android·开发工具·移动端
AirDroid_cn13 小时前
在家找不到手机?除了语音助手,还可以用远程控制!
android·智能手机·远程控制·手机使用技巧·远程控制手机
Good_tea_h20 小时前
Android中如何处理运行时权限?
android