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)

实现效果为:

相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
7177772 天前
研发平台选哪家比较好:2026年主流平台对比与Gitee选型指南
人工智能·gitee
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas