当前位置: 首页 > news >正文

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

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)

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

相关文章:

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

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&…...

达索系统亮相第三十一届中国汽车工程学会年会暨展览会

伴随着改革开放以及中国入世WTO&#xff0c;三十多年来&#xff0c;中国汽车产销已经成为世界最大的单一市场而独占鳌头。近十年来&#xff0c;另辟蹊径的中国汽车产业人在新能源汽车赛道上引领了一波又一波令全球惊艳的创新成就&#xff0c;成为最为靓丽的新出口三大件的头牌。…...

Python网络爬虫实践案例:爬取猫眼电影Top100

以下是一个Python网络爬虫的实践案例&#xff0c;该案例将演示如何使用Python爬取猫眼电影Top100的电影名称、主演和上映时间等信息&#xff0c;并将这些信息保存到TXT文件中。此案例使用了requests库来发送HTTP请求&#xff0c;使用re库进行正则表达式匹配&#xff0c;并包含详…...

ROSSERIAL与Arduino IDE交叉开发(UBUNTU环境,包含ESP32、arduino nano)

ROSSERIAL与Arduino IDE交叉开发 一、简介二、安装1、Ubuntu下的Arduino IDE安装 **针对ESP32报错问题原因溯源和修改**三、运行结点 一、简介 这个教程展示在ubuntu环境下如何利用Arduino IDE配合rosserial开发机器人部件。通过Arduino IDErosserial实现arduino/esp32开发板通…...

爬虫开发工具与环境搭建——使用Postman和浏览器开发者工具

第三节&#xff1a;使用Postman和浏览器开发者工具 在网络爬虫开发过程中&#xff0c;我们经常需要对HTTP请求进行测试、分析和调试。Postman和浏览器开发者工具&#xff08;特别是Network面板和Console面板&#xff09;是两种最常用的工具&#xff0c;能够帮助开发者有效地捕…...

ceph 18.2.4二次开发,docker镜像制作

编译环境要求 #需要ubuntu 22.04版本 参考https://docs.ceph.com/en/reef/start/os-recommendations/ #磁盘空间最好大于200GB #内存如果小于100GB 会有OOM的情况发生,需要重跑 目前遇到内存占用最高为92GB替换阿里云ubuntu 22.04源 将下面内容写入/etc/apt/sources.list 文件…...

游戏引擎学习第19天

介绍 这段内容描述了开发者在进行游戏开发时&#xff0c;对于音频同步和平台层的理解和调整的过程。以下是更详细的复述&#xff1a; 开发者表达了他希望今天继续进行的工作内容。他提到&#xff0c;昨天他讲解了一些关于音频的内容&#xff0c;今天他想稍微深入讲解一下他正…...

简单实现vue2响应式原理

vue2 在实现响应式时&#xff0c;是根据 object.defineProperty() 这个实现的&#xff0c;vue3 是通过 Proxy 对象实现&#xff0c;但是实现思路是差不多的&#xff0c;响应式其实就是让 函数和数据产生关联&#xff0c;在我们对数据进行修改的时候&#xff0c;可以执行相关的副…...

TypeScript 中扩展现有模块的用法

declare module 是 TypeScript 中用于扩展现有模块的特性。它允许开发者在已有模块的基础上&#xff0c;添加新的功能&#xff08;比如扩展接口、添加类型声明等&#xff09;。通过 declare module&#xff0c;可以将额外的声明合并到原模块中。以下是用法详解&#xff1a; 用…...