Android实现RecyclerView分组显示功能完整示例(自定义组头和Item布局)

news2025/1/12 16:15:46

实现效果截图:

首先,我们需要为RecyclerView添加一个分组的概念,我们可以创建一个Group类来表示分组,包括分组名称和分组中的数据项列表。代码如下:

public class Group {
    private String name;
    private List<Item> items;

    public Group(String name, List<Item> items) {
        this.name = name;
        this.items = items;
    }

    public String getName() {
        return name;
    }

    public List<Item> getItems() {
        return items;
    }


    public static class Item {
        private String name;
        private String description;

        public Item(String name, String description) {
            this.name = name;
            this.description = description;
        }

        public String getName() {
            return name;
        }

        public String getDescription() {
            return description;
        }
    }
}

然后,我们需要修改RecyclerView的Adapter,使其能够支持分组。我们需要重写getItemCount()方法来返回所有分组中的数据项总数,而不是所有数据项的总数。我们还需要重写getItemViewType()方法来返回不同的视图类型,以便我们能够为每个分组显示一个标题视图。代码如下:

package com.example.recyclerview_group;

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

import java.util.List;

/**
 * @author wh445306
 * @version 1.0
 * @Description GroupAdapter
 * @Date 2023-04-07 14:37
 */
public class GroupAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<Group> groups;

    public GroupAdapter(List<Group> groups) {
        this.groups = groups;
    }

    @Override
    public int getItemCount() {
        int count = 0;
        for (Group group : groups) {
            count += group.getItems().size() + 1;
        }
        return count;
    }

    @Override
    public int getItemViewType(int position) {
        int count = 0;
        for (Group group : groups) {
            int size = group.getItems().size() + 1;
            if (position < count + size) {
                return position == count ? 0 : 1;
            }
            count += size;
        }
        throw new IllegalArgumentException("Invalid position");
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == 0) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_group, parent, false);
            return new GroupViewHolder(view);
        } else {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_item, parent, false);
            return new ItemViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        int count = 0;
        for (Group group : groups) {
            int size = group.getItems().size() + 1;
            if (position < count + size) {
                if (position == count) {
                    GroupViewHolder groupViewHolder = (GroupViewHolder) holder;
                    groupViewHolder.nameTextView.setText(group.getName());
                } else {
                    ItemViewHolder itemViewHolder = (ItemViewHolder) holder;
                    Group.Item item = group.getItems().get(position - count - 1);
                    itemViewHolder.nameTextView.setText(item.getName());
                    itemViewHolder.descriptionTextView.setText(item.getDescription());
                }
                return;
            }
            count += size;
        }
        throw new IllegalArgumentException("Invalid position");
    }

    private static class GroupViewHolder extends RecyclerView.ViewHolder {
        private TextView nameTextView;

        public GroupViewHolder(View itemView) {
            super(itemView);
            nameTextView = itemView.findViewById(R.id.GroupName);
        }
    }

    private static class ItemViewHolder extends RecyclerView.ViewHolder {
        private TextView nameTextView;
        private TextView descriptionTextView;

        public ItemViewHolder(View itemView) {
            super(itemView);
            nameTextView = itemView.findViewById(R.id.ItemName);
            descriptionTextView = itemView.findViewById(R.id.ItemDescription);
        }
    }
}

最后,我们需要在Activity或Fragment中创建RecyclerView和GroupAdapter,并将其设置为RecyclerView的Adapter。代码如下:

package com.example.recyclerview_group;

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

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        List<Group> groups= new ArrayList<>();
        List<Group.Item> items1 = new ArrayList<>();
        items1.add(new Group.Item("Item 1", "Description 1"));
        items1.add(new Group.Item("Item 2", "Description 2"));
        items1.add(new Group.Item("Item 3", "Description 3"));
        groups.add(new Group("Group 1", items1));
        List<Group.Item> items2 = new ArrayList<>();
        items2.add(new Group.Item("Item 4", "Description 4"));
        items2.add(new Group.Item("Item 5", "Description 5"));
        groups.add(new Group("Group 2", items2));
        List<Group.Item> items3 = new ArrayList<>();
        items3.add(new Group.Item("Item 6", "Description 6"));
        items3.add(new Group.Item("Item 7", "Description 7"));
        groups.add(new Group("Group 3", items3));

        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(new GroupAdapter(groups));
    }
}

activity_main

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <!-- RecyclerView控件 -->
    <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/footerTextView"
            android:padding="16dp" />

    <!-- TextView控件 -->
    <TextView
            android:id="@+id/footerTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:gravity="center"
            android:padding="16dp"
            android:text="Footer Text" />

</RelativeLayout>

item_group定义

item_group用于指定RecyclerView的分组标题视图的布局文件。

在这个示例中,我们使用了一个TextView控件来显示分组标题,使用了android:background属性来设置标题背景颜色,使用了android:textColor属性来设置标题文本颜色。这个布局文件可以根据实际需求来进行修改和定制。

下面是一个简单的item_group.xml示例代码,包含一个TextView控件,用于显示分组标题:

 

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/GroupName"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:background="@color/colorAccent"
          android:padding="16dp"
          android:textColor="@android:color/white" />

item_item定义

`R.layout.item_item用于指定 RecyclerView 的数据项视图的布局文件。

在这个示例中,我们使用了两个 TextView 控件来显示 RecyclerView 的数据项的名称和描述,使用了 android:textSize 属性来设置文本大小,使用了 android:textStyle 属性来设置文本样式,使用了 android:textColor 属性来设置文本颜色。这个布局文件可以根据实际需求来进行修改和定制。

下面是一个简单的 item_item.xml 示例代码,包含两个 TextView 控件,用于显示 RecyclerView 的数据项的名称和描述:

<?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="wrap_content"
              android:orientation="vertical"
              android:padding="16dp">

    <TextView
            android:id="@+id/ItemName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:textStyle="bold" />

    <TextView
            android:id="@+id/ItemDescription"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textColor="@android:color/darker_gray" />

</LinearLayout>

 

这样,我们就实现了RecyclerView的分组功能。在GroupAdapter中,我们重写了getItemCount()、getItemViewType()、onCreateViewHolder()和onBindViewHolder()方法,使其能够支持分组。在Activity或Fragment中,我们创建了RecyclerView和GroupAdapter,并将其设置为RecyclerView的Adapter,从而实现了分组功能。

在这个示例中,我们使用了RelativeLayout布局来包含RecyclerView和TextView控件。RecyclerView控件的高度设置为match_parent,以便占据整个布局。TextView控件的高度设置为wrap_content,以便根据文本内容自适应高度。RecyclerView控件的底部与TextView控件的顶部相对齐,使用了android:layout_above="@+id/footerTextView"属性来实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/416261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT-5到底有多强?Battle!咱貌似也不输呀!

盘点今年的热点话题&#xff0c;ChatGPT是不可避免要被反复提及的一part。从去年的-3.0到今年的-3.5&#xff0c;再到上月刚发布-4.0。从用户体验和市场反馈来讲&#xff0c;这半年的时间&#xff0c;ChatGPT每一步都走得又稳又快&#xff01; 回想起今年2月初ChatGPT全网爆火的…

最短路径-dijkstra/floyd

目录 floyd -dijkstra floyd floyd:用来求所有顶点之间的最短路径问题,求最短路径具体节点顺序&#xff0c;求各点之间最短路径长度 理解floyd&#xff1a; 二维矩阵图&#xff0c;就是不断通过测试新的节点k&#xff0c;看看k节点能不能作为中间节点优化各点之间的最短距离…

SourceMap源码映射详细讲解

SourceMap源码映射详细讲解 前端工程打包后代码会跟项目源码不一致&#xff0c;当代码运行出错时控制台上定位出错代码的位置跟项目源码上不对应。这时候我们很难定位错误代码的位置。SourceMap的用途是可以将转换后的代码映射回源码&#xff0c;如果设置了js文件对应的map资源…

Java每日一练(20230416)

目录 1. 三数之和 &#x1f31f;&#x1f31f; 2. 基本计算器 &#x1f31f;&#x1f31f;&#x1f31f; 3. 通配符匹配 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java…

Android:编译libevent动态库并移植jni中,在Android AVD虚拟机上实现一个http服务器

libevent源码&#xff1a;libevent-2.1.8-stable Android Studio版本&#xff1a;Android Studio Electric Eel | 2022.1.1 Patch 2 AVD虚拟机为x86. https://developer.android.google.cn/studio/run/emulator-networking?hlzh-cn#connecting 大体步骤&#xff1a; 1.在ws…

Vue2_01_data_插值

插值语法 {{name}} data: vue实例的数据对象 data中数据变化时将重新渲染容器 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><!--引入vue,引入之后vue.js 创建了一个全局变…

c语言进阶篇_动态内存管理(数组可以自动扩容?)

前言 &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&#x1f32f; c语言初阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f349;本篇简介:>:讲解c语言中的动态内存管理知识,涉及malloc函数、call…

微信小程序运行及更新机制

微信小程序运行及更新机制1、微信小程序运行机制1.1 前台和后台1.2 小程序启动&#xff1a;冷启动和热启动1.3 小程序销毁2、微信小程序更新机制2.1 启动时同步更新定期检查发现版本更新用户长时间未使用小程序2.2 启动时异步更新开发者手动触发更新2.3 小程序管理后台的相关设…

软件测试分类详解

一图看清软件测试分类 一、按测试技术分&#xff08;是否查看代码&#xff09; **1. 黑盒测试**&#xff1a;软件功能是否正常使用【功能的测试】 **2. 白盒测试**&#xff1a;代码逻辑是否正确【结构的测试】 **3. 灰盒测试**&#xff1a;介于两者之间的测试&#xff0c;也…

第12章_集合框架

第12章_集合框架 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 集合框架概述 1.1 生活中的容器 1.2 数组的特点与弊端 一方面&#xff0c;面向对象语言对事物的体现都是以对…

iOS 项目嵌入Flutter 运行

一 创建Flutter 模块命令行flutter create --template module my_flutter创建完成后&#xff0c;该模块和普通的Flutter项目一直&#xff0c;可以通过Android Studio或VSCode打开、开发、运行&#xff1b;和之前项目不同的iOS和Android项目是一个隐藏文件&#xff0c;并且我们…

黑马点评缓存练习题shop-type缓存,附带详细解析

黑马点评缓存练习题shop-type缓存 依照shop详情的缓存 Controller代码 public class ShopTypeController {Resourceprivate IShopTypeService typeService;GetMapping("list")public Result queryTypeList() {return typeService.queryList();} }创建service接口方…

SentenceTransformers介绍

SentenceTransformer使用范例 1使用SentenceTransformers获得句子向量嵌入 from sentence_transformers import SentenceTransformer#模型下载 model SentenceTransformer(paraphrase-MiniLM-L6-v2)# 编码句子 sentences [Python is an interpreted high-level general-pur…

JavaScript【五】JavaScript中的对象

文章目录&#x1f31f;前言&#x1f31f;对象&#xff1a;&#x1f31f;声明对象&#xff1a;&#x1f31f;隐式创建对象&#xff1a;&#x1f31f;实例化Object&#xff1a;&#x1f31f;实例化自定义构造函数&#xff1a;(会重复占用内存)&#x1f31f;new运算符具体做了什么…

自动内存管理之【常量池】

首先上一段代码&#xff0c;一起思考&#xff0c;打印的结果&#xff0c;基于jdk1.8。 StringBuilder sbnew StringBuilder("我爱我媳妇儿");String s sb.toString();System.out.println(s.intern()s); //falsesb.append("&#xff0c;她也很爱我&#xff01;&…

C++——入门讲解

作者&#xff1a;几冬雪来 时间&#xff1a;2023年4月16日 内容&#xff1a;C入门讲解 目录 前言&#xff1a; 1.什么是C&#xff1a; 2.C关键字&#xff1a; 3.命名冲突&#xff1a; 4.域和::操作符&#xff1a; 5.std内容讲解&#xff1a; 6.<<符&#xff1a…

STM32F4_独立看门狗详解(IWDG)

目录 1. 独立看门狗是什么 2. 独立看门狗 IWDG简介 3. 独立看门狗的主要特性 4. 独立看门狗功能 4.1 独立看门狗功能框图 4.2 IWDG寄存器 4.2.1 关键字寄存器 IWDG_KR 4.2.2 预分频器寄存器 IWDG_PR 4.2.3 重载寄存器 IWDG_RLR 4.2.4 状态寄存器 IWDG_SR 5. 库函数…

OpenCV实战之人脸美颜美型(六)——磨皮

1.需求分析 有个词叫做“肤若凝脂”,直译为皮肤像凝固的油脂,形容皮肤洁白且光润,这是对美女的一种通用评价。实际生活中我们的皮肤多少会有一些毛孔、斑点等表现,在观感上与上述的“光润感”相反,因此磨皮也成为美颜算法中的一项基础且重要的功能。让皮肤变得更加光润,就…

interface陷阱

A1 interface Duck Typing: 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子&#xff0c;那么这只鸟就可以被称为鸭子 目的: 在 Go 中&#xff0c;Interface&#xff08;接口&#xff09;只是一组方法集合。描述事物的外部行为而非内部结构。 通过接口实现多态的概…

微服务架构——SpringCloud快速入门

认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 单体架构 将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署。 优点&#…