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

ops/2024/11/25 14:52:18/

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"><TextViewandroid: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"/><ImageViewandroid: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.LogdUtilclass 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 = falseholder.treeItem.setBackgroundResource(R.color.white)}mCurrentDataList[position].isSelect = truenotifyDataSetChanged()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))}//判断层级,显示marginval 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.VISIBLEif (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 = 1000val 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: TreeClickInterfacefun 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.RecyclerViewandroid: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 = adapterbinding.recyclerView.layoutManager =LinearLayoutManager(this@EquipmentStateActivity, LinearLayoutManager.VERTICAL, false)

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


http://www.ppmy.cn/ops/136598.html

相关文章

【Spring】RESTful设计风格

前言 REST(Representational State Transfer),即“表现层状态转移”,它定义了互联网软件服务的架构原则。如果一个架构的符合 REST 原则&#xff0c;就被称之为 RESTful 架构&#xff0c;这是目前最流行的互联网软件服务架构设计风格之一。 REST 并不是一种标准&#xff0c;…

深度学习中的循环神经网络(RNN)与时间序列预测

一、循环神经网络&#xff08;RNN&#xff09;简介 循环神经网络&#xff08;Recurrent Neural Networks&#xff0c;简称RNN&#xff09;是一种专门用于处理序列数据的神经网络架构。与传统神经网络不同&#xff0c;RNN具有内部记忆能力&#xff0c;能够捕捉数据中的时间依赖…

(免费送源码)计算机毕业设计原创定制:Java+SSM+JSP+Ajax+MySQLSSM国外鞋服代购平台

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;鞋服代购平台当然也不例外。代购平台是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;采用…

深度学习1

一、库的安装 1、cuda/cpu cuda 有最好&#xff0c;没有无需额外安装&#xff1b;cpu无需其他操作&#xff0c;直接进入下面步骤 查看 nvidia 驱动版本&#xff1a;cmd里面&#xff0c;输入nvidia-smi 查看GPU驱动程序版本 CUDA Version位置&#xff08;保证CUDA版本号<GPU…

Odoo :免费且开源的农牧行业ERP管理系统

文 / 开源智造Odoo亚太金牌服务 引言 提供农牧企业数字化、智能化、无人化产品服务及全产业链高度协同的一体化解决方案&#xff0c;提升企业智慧种养、成本领先、产业互联的核心竞争力。 行业典型痛点 一、成本管理粗放&#xff0c;效率低、管控弱 产品研发过程缺少体系化…

ApiChain 从迭代测试用例到项目回归测试 核心使用教程

项目地址&#xff1a;ApiChain 项目主页 环境变量 环境变量是在特定的开发环境&#xff08;开发、测试、uat等&#xff09;下&#xff0c;保存的一份数据集&#xff0c;环境变量是发送网络请求或者执行单测的一个重要数据源。环境变量根据作用范围可以分为全局环境变量、项目…

OAuth2资源服务器白名单接口带token被拦截

在资源服务器的配置中&#xff0c;添加了请求白名单&#xff0c;如下 Configuration EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter {Autowiredprivate OAuth2Properties properties;Overridepublic void configure(HttpSe…

超高流量多级缓存架构设计!

文章内容已经收录在《面试进阶之路》&#xff0c;从原理出发&#xff0c;直击面试难点&#xff0c;实现更高维度的降维打击&#xff01; 文章目录 电商-多级缓存架构设计多级缓存架构介绍多级缓存请求流程负载均衡算法的选择轮询负载均衡一致性哈希负载均衡算法选择 应用层 Ngi…