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">
<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、在展开过程中,需要注意的是直接在父项的下方进行数据的添加,而移除的话就是需要递归移除数据
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
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.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、实现代码
//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)
实现效果为: