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)

实现效果为:

相关推荐
xiangpanf2 小时前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx5 小时前
安卓线程相关
android
消失的旧时光-19435 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon6 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon6 小时前
VSYNC 信号完整流程2
android
dalancon6 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户69371750013847 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android8 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才8 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶9 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle