安卓开发级联显示菜单-省市区显示举例
问题背景
安卓日常开发过程,经常会有需要级联显示的场景,比如省市区显示等,或者各种组织结构级联显示,本文将介绍安卓开发过程实现级联显示的一种方案。
实现效果如下:
问题分析
思路分析:
考虑将要是的省、市、区设计成一种字典迭代结构,数据结构如下:
/**
* 组织实体类
*/
class Organization(var name: String, var subList: MutableList<Organization>?)
这种数据结构,当前页面即可显示当前组织的子列表内容,比较方便。
话不多少,直接上代码:
(1)数据结构实体类
/**
* 组织实体类
*/
class Organization(var name: String, var subList: MutableList<Organization>?)
(2)页面显示activity,代码如下:
package com.baorant.kotlinorganization
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import com.baorant.kotlinorganization.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var activityMainBinding: ActivityMainBinding
private lateinit var topListAdapter : TopAdapter
private val topList = mutableListOf<Organization>()
private val organizationList = mutableListOf<Organization>()
private lateinit var subOrgListAdapter : OrganizationAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
initView()
initData()
}
private fun initData() {
// 模拟省市区级联数据
val organization111 = Organization("南关区", null);
val organization112 = Organization("朝阳区", null);
val organization113 = Organization("绿园区", null);
val organization110List = ArrayList<Organization>()
organization110List.add(organization111)
organization110List.add(organization112)
organization110List.add(organization113)
val organization121 = Organization("丰满区", null);
val organization122 = Organization("龙潭区", null);
val organization123 = Organization("蛟河区", null);
val organization120List = ArrayList<Organization>()
organization120List.add(organization121)
organization120List.add(organization122)
organization120List.add(organization123)
val organization11 = Organization("长春市", organization110List)
var organization12 = Organization("吉林市", organization120List)
val organization11List = ArrayList<Organization>()
organization11List.add(organization11)
organization11List.add(organization12)
val organization1 = Organization("吉林省", organization11List);
organizationList.add(organization1)
subOrgListAdapter.notifyDataSetChanged()
}
private fun initView() {
// 显示层级的横向列表
val layoutManager = LinearLayoutManager(this)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
activityMainBinding.recyclerView.layoutManager = layoutManager
topListAdapter = TopAdapter(topList)
topListAdapter.setOnItemClickListener(object: OnItemClickListener{
override fun onItemClick(view: View, position: Int) {
val organization = topList[position]
organizationList.clear()
organization.subList?.let { organizationList.addAll(it) }
subOrgListAdapter.notifyDataSetChanged()
val temList = mutableListOf<Organization>()
for (index in topList.indices) {
if (index <= position) {
temList.add(topList[index])
}
}
topList.clear()
topList.addAll(temList)
topListAdapter.notifyDataSetChanged()
}
})
activityMainBinding.recyclerView.adapter = topListAdapter
// 展示当前层级子项的纵向列表
val subLayoutManager = LinearLayoutManager(this)
activityMainBinding.subOrgList.layoutManager = subLayoutManager
subOrgListAdapter = OrganizationAdapter(organizationList)
subOrgListAdapter.setOnItemClickListener(object : OnItemClickListener {
override fun onItemClick(view: View, position: Int) {
val organization = organizationList[position]
if (organization.subList == null) {
return
}
organizationList.clear()
organization.subList?.let { organizationList.addAll(it) }
subOrgListAdapter.notifyDataSetChanged()
topList.add(organization)
topListAdapter.notifyDataSetChanged()
}
})
activityMainBinding.subOrgList.adapter = subOrgListAdapter
}
}
(3)activity对应布局layout文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_alignParentTop="true">
<LinearLayout
android:id="@+id/ll_top_recycler"
android:layout_width="match_parent"
android:layout_height="42dp"
android:background="@color/white"
android:gravity="center_horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scrollbars="none" />
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ll_top_recycler"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--subOrg-->
<TextView
android:layout_marginTop="10dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="下级内容列表" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/subOrgList"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
(4)纵向子列表对应adapter,代码如下:
package com.baorant.kotlinorganization
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
/**
* 纵向子列表对应adapter
*/
class OrganizationAdapter(var organizationList:List<Organization>) : RecyclerView.Adapter<OrganizationAdapter.ViewHolder>() {
private lateinit var onItemClickListener: OnItemClickListener
//在内部类里面获取到item里面的组件
inner class ViewHolder(view:View):RecyclerView.ViewHolder(view){
var newName:TextView=view.findViewById(R.id.name)
}
//重写的第一个方法,用来给制定加载那个类型的Recycler布局
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item,parent,false)
val viewHolder = ViewHolder(view)
//单机事件
viewHolder.itemView.setOnClickListener {
val position = viewHolder.adapterPosition
onItemClickListener.onItemClick(viewHolder.itemView, position)
}
return viewHolder
}
fun setOnItemClickListener(listener: OnItemClickListener) {
this.onItemClickListener = listener
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val organization = organizationList[position]
holder.newName.text = organization.name
}
override fun getItemCount(): Int {
return organizationList.size
}
}
(5)上方横向列表对应adapter,代码如下:
package com.baorant.kotlinorganization
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
/**
* 上方横向列表对应adapter
*/
class TopAdapter(var organizationList:List<Organization>) : RecyclerView.Adapter<TopAdapter.ViewHolder>() {
private lateinit var onItemClickListener: OnItemClickListener
//在内部类里面获取到item里面的组件
inner class ViewHolder(view:View):RecyclerView.ViewHolder(view){
var newName:TextView=view.findViewById(R.id.name)
}
//重写的第一个方法,用来给制定加载那个类型的Recycler布局
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
Log.d("baorant", "onCreateViewHolder begin")
val view = LayoutInflater.from(parent.context).inflate(R.layout.top_list_item,parent,false)
val viewHolder = ViewHolder(view)
// 点击事件
viewHolder.itemView.setOnClickListener {
val position = viewHolder.adapterPosition
onItemClickListener.onItemClick(viewHolder.itemView, position)
}
return viewHolder
}
fun setOnItemClickListener(listener: OnItemClickListener) {
this.onItemClickListener = listener
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Log.d("baorant", "onBindViewHolder begin")
val organization = organizationList[position]
holder.newName.text = organization.name
}
override fun getItemCount(): Int {
Log.d("baorant", "getItemCount begin")
return organizationList.size
}
}
(6)自定义接口,代码如下:
/**
* 自定义接口,适配recyclerview点击事件adapter
*/
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
}
问题总结
本文介绍了安卓开发过程实现级联显示的一种方案,有兴趣的同学可以进一步深入研究。