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)
实现效果为: