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

1、adapter-item的布局

java 复制代码
<?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、在展开过程中,需要注意的是直接在父项的下方进行数据的添加,而移除的话就是需要递归移除数据

java 复制代码
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

java 复制代码
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、实现布局

java 复制代码
<?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、实现代码

java 复制代码
//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)

实现效果为:

相关推荐
拭心9 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
行者彡9 小时前
gitee别人仓库再上传自己仓库
gitee
sin22019 小时前
git推送本地仓库到远程(Gitee)
git·gitee
带电的小王11 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡11 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道12 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库12 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道13 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe13 小时前
Android Hook - 动态加载so库
android
居居飒14 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin