20241121 android中树结构列表(使用recyclerView实现)

news2024/11/23 12:07:44

1、adapter-item的布局

<?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:id="@+id/item_cl"
    android:padding="@dimen/dp_10"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <TextView
        android:id="@+id/item_label"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toEndOf="@id/item_down_iv"
        app:layout_constraintBottom_toBottomOf="parent"
        />
    <ImageView
        android:id="@+id/item_down_iv"
        android:layout_width="@dimen/dp_20"
        android:layout_height="@dimen/dp_20"
        android:src="@mipmap/icon_tree_export"
        android:visibility="visible"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/item_label"
        app:layout_constraintTop_toTopOf="parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

2、adapter的设计代码

使用最简单的方式进行实现树状结构,并对展开和关闭进行处理
1、将树状结构数据整理成list结构
2、初始化展示效果
3、在展开过程中,需要注意的是直接在父项的下方进行数据的添加,而移除的话就是需要递归移除数据

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import cn.lisi.envirolablims.R
import cn.lisi.envirolablims.client.adapter.TreeItemAdapter.TreeViewHolder
import cn.lisi.envirolablims.client.bean.response.DeptTreeBean
import cn.lisi.envirolablims.client.bean.response.DeptTreeInfo
import cn.lisi.envirolablims.client.util.LogdUtil

class TreeItemAdapter(val mContext: Context) : RecyclerView.Adapter<TreeViewHolder>() {

    /**
     * 所有的数据
     */
    private val mDataList: MutableList<DeptTreeBean> = ArrayList()
    private var mCurrentDataList: MutableList<DeptTreeBean> = ArrayList()
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TreeViewHolder {


        return TreeViewHolder(
            LayoutInflater.from(mContext).inflate(R.layout.rc_item_tree_item_layout, parent, false)
        )
    }

    override fun getItemCount(): Int {
        return mCurrentDataList.size
    }

    fun submitDataList(dataList: MutableList<DeptTreeInfo>) {
        initTreeList(dataList, 0, -1L, false, false)
        initCurrentTreenList()
        notifyDataSetChanged()
    }


    override fun onBindViewHolder(holder: TreeViewHolder, position: Int) {
        holder.treeText.text = mCurrentDataList[position].label

        //根据点击修改效果
        holder.treeItem.setOnClickListener {
            mCurrentDataList.forEach { item ->
                item.isSelect = false
                holder.treeItem.setBackgroundResource(R.color.white)
            }
            mCurrentDataList[position].isSelect = true
            notifyDataSetChanged()
            mTreeClickInterface.itemClickListener(position,mCurrentDataList[position])
        }

        holder.treeText.setTextColor(mContext.getColor(R.color.black))
        if (mCurrentDataList[position].isSelect) {
            holder.treeText.setTextColor(mContext.getColor(R.color.blue_green))
        }

        //判断层级,显示margin
        val paramMargin = (holder.treeItem.layoutParams as LinearLayout.LayoutParams)
        paramMargin.setMargins(
            (50 * (mCurrentDataList[position].level) + 24),
            0,
            0,
            0
        )
        holder.treeItem.layoutParams = paramMargin

        //判断是否有子项
        if (mCurrentDataList[position].isHasChild) {
            holder.treeImage.visibility = View.VISIBLE
            if (mCurrentDataList[position].isExport) {
                holder.treeImage.setImageResource(R.mipmap.icon_tree_export)
            } else {
                holder.treeImage.setImageResource(R.mipmap.icon_tree_import)
            }

            holder.treeImage.setOnClickListener {
                //展开
                if (mCurrentDataList[position].isExport) {

                    //跨层次移除
                    removeItemList(mCurrentDataList[position].id)
                    mCurrentDataList[position].isExport = false

                } else {

                    val insetList: MutableList<DeptTreeBean> = ArrayList()
                    mDataList.forEach { item ->
                        if (item.parentId == mCurrentDataList[position].id) {
                            insetList.add(item)
                            LogdUtil.e("initCustomerShownList", "item 增加的数据 $item")
                            //在展开的之后增加,而不是最后增加
                        }
                    }
                    mCurrentDataList = initCustomerShownList (mCurrentDataList, mCurrentDataList[position].id, insetList)
                    mCurrentDataList[position].isExport = true
                }

                notifyDataSetChanged()
            }
        } else {
            holder.treeImage.visibility = View.GONE
        }


    }

    private fun removeItemList(parentId: Long) {
        mDataList.forEach { item ->
            if (parentId == item.parentId){
                mCurrentDataList.remove(item)
                if (item.isHasChild){
                    removeItemList(item.id)
                }
            }
        }

    }

    private fun initCustomerShownList(currentDataList:MutableList<DeptTreeBean>,parentId: Long, insetList: MutableList<DeptTreeBean>):MutableList<DeptTreeBean> {

        var currentIndex = 1000
        val endList: MutableList<DeptTreeBean> = ArrayList()
        val startList: MutableList<DeptTreeBean> = ArrayList()

        currentDataList.forEach { item ->
            if (item.id == parentId) {
                currentIndex = currentDataList.indexOf(item)
            }
            if (currentDataList.indexOf(item) > currentIndex) {
                endList.add(item)
            }else{
                startList.add(item)
            }
        }
        currentDataList.clear()
        currentDataList.addAll(startList)
        currentDataList.addAll(insetList)
        currentDataList.addAll(endList)

        return currentDataList
    }


    /**
     * 将树结构整合成列表形式
     */
    private fun initTreeList(
        dataList: MutableList<DeptTreeInfo>,
        level: Int,
        parentId: Long,
        isExport: Boolean,
        isSelect: Boolean
    ) {
        dataList.forEach { info ->
            mDataList.add(
                DeptTreeBean(
                    id = info.id,
                    label = info.label,
                    level = level,
                    isHasChild = !info.children.isNullOrEmpty(),
                    parentId = parentId,
                    isExport = isExport,
                    isSelect = isSelect
                )
            )
            if (!info.children.isNullOrEmpty()) {
                initTreeList(info.children, level + 1, info.id, isExport, isSelect)
            }

        }

    }

    /**
     * 设置初始展示效果
     */
    private fun initCurrentTreenList() {
        mCurrentDataList.clear()
        mDataList.forEach { info ->
            if (info.level == 0) {
                //展开
                mCurrentDataList.add(info)

            }

        }
    }

    class TreeViewHolder(val itemView: View) : RecyclerView.ViewHolder(itemView) {
        val treeItem = itemView.findViewById<LinearLayout>(R.id.item_cl)
        val treeText = itemView.findViewById<TextView>(R.id.item_label)
        val treeImage = itemView.findViewById<ImageView>(R.id.item_down_iv)

    }

    private lateinit var mTreeClickInterface: TreeClickInterface

    fun setOnClickListener(clickInterface:TreeClickInterface){
        mTreeClickInterface = clickInterface
    }
    interface TreeClickInterface{
        fun itemClickListener(position: Int,bean:DeptTreeBean)
    }
}

3、树状adapter的bean

data class DeptTreeInfo(val children: MutableList<DeptTreeInfo>? = ArrayList(), val id: Long, val label: String)

data class DeptTreeBean(
    val id: Long,
    val label: String,
    val level: Int,
    val isHasChild: Boolean,
    val parentId: Long,
    var isExport: Boolean,
    var isSelect:Boolean
)

4、实现布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:ignore="MissingDefaultResource">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="@dimen/margin_20dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
 

</androidx.constraintlayout.widget.ConstraintLayout>

5、实现代码


//EquipmentDeptTreeList为所需的树结构数据
val adapter = TreeItemAdapter(this)
        //  adapter.submitDataList(GloableLocalStore.EquipmentDeptTreeList)
        adapter.submitDataList(
            mutableListOf(
                DeptTreeInfo(
                    mutableListOf(
                        DeptTreeInfo(
                            children = null,
                            id = 1,
                            label = "数字1"
                        ),
                        DeptTreeInfo(
                            children = null,
                            id = 2,
                            label = "数字2"
                        ),
                        DeptTreeInfo(
                            children = mutableListOf(
                                DeptTreeInfo(
                                    children = mutableListOf(
                                        DeptTreeInfo(
                                            children = null,
                                            id = 311,
                                            label = "数字311"),
                                        DeptTreeInfo(
                                            children = null,
                                            id = 312,
                                            label = "数字312")),
                                    id = 31,
                                    label = "数字31"),
                                DeptTreeInfo(
                                    children = null,
                                    id = 32,
                                    label = "数字32")),
                            id = 3,
                            label = "数字3"
                        ),
                       DeptTreeInfo(
                            children = mutableListOf(
                                DeptTreeInfo(
                                    children = mutableListOf(
                                        DeptTreeInfo(
                                            children = mutableListOf(
                                                DeptTreeInfo(
                                                    children = null,
                                                    id = 4111,
                                                    label = "数字4111"),
                                                DeptTreeInfo(
                                                    children = null,
                                                    id = 4112,
                                                    label = "数字4112")),
                                            id = 411,
                                            label = "数字411"),
                                        DeptTreeInfo(
                                            children = mutableListOf(
                                                DeptTreeInfo(
                                                    children = null,
                                                    id = 4121,
                                                    label = "数字4121"),
                                                DeptTreeInfo(
                                                    children = null,
                                                    id = 4122,
                                                    label = "数字4122")),
                                            id = 412,
                                            label = "数字412")),
                                    id = 41,
                                    label = "数字41"),
                                DeptTreeInfo(
                                    children = null,
                                    id = 42,
                                    label = "数字42")),
                            id = 4,
                            label = "数字4"
                        ),
                        DeptTreeInfo(
                            children = mutableListOf(
                                DeptTreeInfo(
                                    children = null,
                                    id = 51,
                            label = "数字51"),
                                DeptTreeInfo(
                                    children = null,
                                    id =52,
                            label = "数字52")),
                            id = 5,
                            label = "数字5"
                        ),
                        DeptTreeInfo(
                            children = null,
                            id = 6,
                            label = "数字6"
                        )
                    ), id = 0, label = "数字0"
                )
            )
        )
        adapter.setOnClickListener(object : TreeItemAdapter.TreeClickInterface {
            override fun itemClickListener(position: Int, bean: DeptTreeBean) {
                LogdUtil.d("lucky","点击获取的数据 position $position \n bean $bean")
            }

        })
        binding.recyclerView.adapter = adapter

        binding.recyclerView.layoutManager =
            LinearLayoutManager(this@EquipmentStateActivity, LinearLayoutManager.VERTICAL, false)


实现效果为:
在这里插入图片描述

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

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

相关文章

Kubernetes的pod控制器

文章目录 一&#xff0c;什么是pod控制器二&#xff0c;pod控制器类型&#xff08;重点&#xff09;1.ReplicaSet2.Deployment3.DaemonSet4.StatefulSet5.Job6.Cronjob 三&#xff0c;pod与控制器的关系1.Deployment2.SatefulSet2.1StatefulSet组成2.2headless的由来2.3有状态服…

网口输出的加速度传感器

一、功能概述 1.1 设备简介 本模块为了对电机、风机、水泵等旋转设备进行预测性运维而开发&#xff0c;只需一个模块&#xff0c; 就可以采集旋转设备的 3 路振动信号&#xff08;XYZ 轴&#xff09;和一路温度信号&#xff0c;防护等级 IP67 &#xff0c;能够 适应恶劣的工业…

RocketMQ: 部署结构与存储特点

RocketMQ 是什么 它是一个队列模型的消息中间件&#xff0c;具有高性能、高可靠、高实时、分布式特点 Producer、Consumer、队列都可以分布式Producer 向一些队列轮流发送消息 队列集合称为 TopicConsumer 如果做广播消费则一个 consumer 实例消费这个 Topic 对应的所有队列如果…

【Python系列】浅析 Python 中的字典更新与应用场景

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

正版Simsolid快速无网格划分工具软件

相信各位结构工程师、产品设计工程师、仿真分析师们对SimSolid都不陌生&#xff0c;Altair SimSolid 是一款革命性的仿真软件&#xff0c;旨在为结构分析提供快速而准确的解决方案。SimSolid的独特之处在于它可以直接在完整的设计几何体上进行复杂的仿真&#xff0c;无需传统的…

DevOps-Jenkins-新手入门级

1. Jenkins概述 1. Jenkins是一个开源持续集成的工具&#xff0c;是由JAVA开发而成 2. Jenkins是一个调度平台&#xff0c;本身不处理任何事情&#xff0c;调用插件来完成所有的工作 1.1 什么是代码部署 代码发布/部署>开发书写的程序代码---->部署测试/生产环境 web服务…

Lucene(2):Springboot整合全文检索引擎TermInSetQuery应用实例附源码

前言 本章代码已分享至Gitee: https://gitee.com/lengcz/springbootlucene01 接上文。Lucene(1):Springboot整合全文检索引擎Lucene常规入门附源码 如何在指定范围内查询。从lucene 7 开始&#xff0c;filter 被弃用&#xff0c;导致无法进行调节过滤。 TermInSetQuery 指定…

tensorflow案例7--数据增强与测试集, 训练集, 验证集的构建

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 这次主要是学习数据增强, 训练集 验证集 测试集的构建等等的基本方法, 数据集还是用的上一篇的猫狗识别;基础篇还剩下几个, 后面的难度会逐步提升;欢迎…

ssm面向品牌会员的在线商城小程序

摘要 随着Internet的发展&#xff0c;人们的日常生活已经离不开网络。未来人们的生活与工作将变得越来越数字化&#xff0c;网络化和电子化。它将是直接管理面向品牌会员的在线商城小程序的最新形式。本小程序是以面向品牌会员的在线商城管理为目标&#xff0c;使用 java技术制…

国土安全部发布关键基础设施安全人工智能框架

美国国土安全部 (DHS) 发布建议&#xff0c;概述如何在关键基础设施中安全开发和部署人工智能 (AI)。 https://www.dhs.gov/news/2024/11/14/groundbreaking-framework-safe-and-secure-deployment-ai-critical-infrastructure 关键基础设施中人工智能的角色和职责框架 https:/…

五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则

一、引言 选择合适的架构模式是一个至关重要的决策&#xff0c;尤其是在单体架构和微服务架构之间的选择&#xff0c;本文将带大家认识什么是单体架构&#xff0c;什么是微服务架构&#xff0c;以及两者如何去选择&#xff0c;如何去转换。 二、什么是单体架构 单体架构&a…

【网络协议】【TCP】精讲TCP数据包传递的地址解析(含三次握手四次挥手图文并茂精华版)

目录 前言 1.TCP定义 1.1 什么是面向连接? 1.2 什么是可靠的通信协议? 1.3 什么是面向字节流的? 2. 数据包传递的地址解析 3. 三次握手过程详解 3.1 第一次握手 3.2 第二次握手 3.3 第三次握手 4. 四次挥手 4.1 第一次挥手 4.2 第二次挥手 4.3 第三次挥手 4.…

Win11 24H2新BUG或影响30%CPU性能,修复方法在这里

原文转载修改自&#xff08;更多互联网新闻/搞机小知识&#xff09;&#xff1a; 一招提升Win11 24H2 CPU 30%性能&#xff0c;小BUG大影响 就在刚刚&#xff0c;小江在网上冲浪的时候突然发现了这么一则帖子&#xff0c;标题如下&#xff1a;基准测试&#xff08;特别是 Time…

人工智能的核心思想-神经网络

神经网络原理 引言 在理解ChatGPT之前&#xff0c;我们需要从神经网络开始&#xff0c;了解最简单的“鹦鹉学舌”是如何实现的。神经网络是人工智能领域的基础&#xff0c;它模仿了人脑神经元的结构和功能&#xff0c;通过学习和训练来解决复杂的任务。本文将详细介绍神经网络…

socket连接封装

效果&#xff1a; class websocketMessage {constructor(params) {this.params params; // 传入的参数this.socket null;this.lockReconnect false; // 重连的锁this.socketTimer null; // 心跳this.lockTimer null; // 重连this.timeout 3000; // 发送消息this.callbac…

蓝桥杯每日真题 - 第17天

题目&#xff1a;&#xff08;最大数字&#xff09; 题目描述&#xff08;13届 C&C B组D题&#xff09; 题目分析&#xff1a; 操作规则&#xff1a; 1号操作&#xff1a;将数字加1&#xff08;如果该数字为9&#xff0c;变为0&#xff09;。 2号操作&#xff1a;将数字…

探索免费的Figma中文版:开启高效设计之旅

在当今数字化设计的浪潮中&#xff0c;Figma以其强大的云端协作功能和出色的设计能力&#xff0c;成为了众多设计师的心头好。而对于国内的设计师来说&#xff0c;能够免费使用Figma中文版更是一大福音&#xff0c;下面就来一起探索一下吧。 一、Figma中文版的获取途径 虽然F…

leetcode:112. 路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点 是指没有子节点…

新160个crackme - 100-E-crackme

运行分析 需根据机器码&#xff0c;填写正确注册码 PE分析 C程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 ida无法搜到字符串&#xff0c;使用暂停法找关键函数 首先启动ida动态调试&#xff0c;点击注册来到错误弹窗 点击Debugger -> Pause process 发现断…

VSCode 间距太小

setting->font family 使用&#xff1a;Consolas, Courier New, monospace 字体