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>
相关推荐
selt7917 小时前
Redisson之RedissonLock源码完全解析
android·java·javascript
Yao_YongChao8 小时前
Android MVI处理副作用(Side Effect)
android·mvi·mvi副作用
非凡ghost9 小时前
JRiver Media Center(媒体管理软件)
android·学习·智能手机·媒体·软件需求
席卷全城9 小时前
Android 推箱子实现(引流文章)
android
齊家治國平天下9 小时前
Android 14 系统中 Tombstone 深度分析与解决指南
android·crash·系统服务·tombstone·android 14
maycho12311 小时前
MATLAB环境下基于双向长短时记忆网络的时间序列预测探索
android
思成不止于此12 小时前
【MySQL 零基础入门】MySQL 函数精讲(二):日期函数与流程控制函数篇
android·数据库·笔记·sql·学习·mysql
brave_zhao12 小时前
达梦数据库(DM8)支持全文索引功能,但并不直接兼容 MySQL 的 FULLTEXT 索引语法
android·adb
sheji341612 小时前
【开题答辩全过程】以 基于Android的网上订餐系统为例,包含答辩的问题和答案
android
easyboot13 小时前
C#使用SqlSugar操作mysql数据库
android·sqlsugar