安卓开发级联显示菜单-省市区显示举例

news2024/10/7 8:26:45

安卓开发级联显示菜单-省市区显示举例

问题背景

安卓日常开发过程,经常会有需要级联显示的场景,比如省市区显示等,或者各种组织结构级联显示,本文将介绍安卓开发过程实现级联显示的一种方案。
实现效果如下:
在这里插入图片描述

问题分析

思路分析
考虑将要是的省、市、区设计成一种字典迭代结构,数据结构如下:

/**
 * 组织实体类
 */
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)
}

问题总结

本文介绍了安卓开发过程实现级联显示的一种方案,有兴趣的同学可以进一步深入研究。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/669523.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GaussDB整体性能慢分析

目录 问题描述问题现象告警业务影响原因分析分析步骤分析定位方法步骤一步骤二步骤三步骤四CPU满I/O满或者I/O异常内存满网络异常 步骤五并发问题数据库配置问题异常等待事件长时间性能下降短时性能抖动不优SQL 问题描述 整体性能慢。不满足客户作业对时延要求或者不满足客户预…

微信小程序 u-picker 三级联动 uView

微信小程序 u-picker 三级联动 uView 场景 移动端微信小程序框架 uView 中的 u-picker 实现三级联动 数据是一级一级加载的 [12,1201,120101] 多列联动 先了解属性参数 mode可以设置为&#xff1a;time、region、selector、multiSelector&#xff0c;区分时间、地区、单列&am…

2022高教社杯全国大学生数学建模竞赛B题解析(更新完结)

2022高教社杯全国大学生数学建模竞赛B题解析&#xff08;更新完结&#xff09; 题目解析前言问题一1.11.21.3问题二 题目 B 题 无人机遂行编队飞行中的纯方位无源定位 无人机集群在遂行编队飞行时&#xff0c;为避免外界干扰&#xff0c;应尽可能保持电磁静默&#xff0c;少向…

LC-LCP 41. 黑白翻转棋

LCP 41. 黑白翻转棋 难度中等32 在 n*m 大小的棋盘中&#xff0c;有黑白两种棋子&#xff0c;黑棋记作字母 "X", 白棋记作字母 "O"&#xff0c;空余位置记作 "."。当落下的棋子与其他相同颜色的棋子在行、列或对角线完全包围&#xff08;中间不…

Kotlin 一劳永逸实现 TAG

1 TAG 经典写法 对于 Android 开发&#xff0c;当我们需要在类中打印 Log 时&#xff0c;通常在Java中会这么定义一个 TAG&#xff1a; private static final String TAG "TestClass"; 或者不具体指定名字&#xff1a; private static final String TAG TestClass.…

Java粮油质量管控防伪溯源系统源码 粮油MES源码

Java粮油质量管控防伪溯源系统源码&#xff0c; 粮油MES源码&#xff0c;有演示&#xff0c;有源码。 一、全生命周期的追踪与溯源 &#xff08;1&#xff09;通过一物一码管理生产销售、追踪包装关联&#xff0c;配送管理及终端查询来实现窜货预警&#xff0c;及时处理问题&…

(一)rstudio容器用户配置root权限,安装conda

1、查看运行中的容器&#xff1a;docker ps 2、进入容器&#xff1a;docker exec -it my_rstudio /bin/bash 3、安装工具&#xff1a;apt-get install 4、查看权限配置文件&#xff1a;cat /etc/sudo 5、查看确认用户(rstudio)&#xff1a;cat /etc/passwd | cut -d: -f1 ro…

判断给定数据中是否存在True只要存在一个True结果为Turenp.sometrue()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 判断给定数据中是否存在True 只要存在一个True结果为Ture np.sometrue() 选择题 下列说法错误的是? import numpy as np a np.array([False, False, True]) print("【显示】a "…

三年时间打磨,MeterSphere v2.10 LTS版本给测试用户带来的价值

2023年5月&#xff0c;MeterSphere开源持续测试平台&#xff08;https://github.com/metersphere&#xff09;发布了v2.10 LTS版本。这是这个开源项目自2020年2月写下第一行代码后发布的第三个LTS版本。 在软件行业&#xff0c;LTS&#xff08;即Long Term Support&#xff09…

SQL太慢如何进行优化

1.慢SQL优化思路。 慢查询日志记录慢SQL explain分析SQL的执行计划 profile 分析执行耗时 Optimizer Trace分析详情 确定问题并采用相应的措施 1.1 慢查询日志记录慢SQL 如何定位慢SQL呢、我们可以通过慢查询日志来查看慢SQL。默认的情况下呢&#xff0c;MySQL数据库是不开…

C盘文件恢复怎么做?数据恢复,就看这4招!

我一般比较重要的文件都会保存到c盘中。最近电脑有点卡顿&#xff0c;想清理一下不需要的文件&#xff0c;但不小心删除了一个很重要的文件&#xff0c;c盘删除的文件还能恢复吗&#xff1f;谁可以帮我想想c盘中的文件如何恢复呢&#xff1f; C盘对于电脑来说是个很重要的磁盘&…

Linux教程——Vim移动光标快捷键汇总

Vim 文本编辑器中&#xff0c;最简单的移动光标的方式是使用方向键&#xff0c;但这种方式的效率太低&#xff0c;更高效的方式使用快捷键。 Vim 移动光标常用的快捷键及其功能如下面各表所示&#xff0c;需要注意的是&#xff0c;表中所有的快捷键都在命令模式&#xff08;默…

安卓蓝牙L2CAP协议简介及报文格式

概述 逻辑链路控制和适配协议&#xff08;Logical Link Control and Adaptation Protocol&#xff0c;L2CAP&#xff09;是蓝牙的核心协议&#xff0c;负责适配基带中的上层协议。它同链路管理器并行工作&#xff0c;向上层协议提供定向连接的和无连接的数据业务。L2CAP具有分…

彻底理解SQL中的JOIN

数据准备 -- 建表语句 CREATE TABLE tbl_dept (id int(11) NOT NULL AUTO_INCREMENT,deptName varchar(30) DEFAULT NULL,locAdd varchar(40) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8;CREATE TABLE tbl_emp (id int(11) NOT NULL …

【运维知识进阶篇】zabbix5.0稳定版详解4(用脚本自定义监控项+监控MySQL状态信息)

我们在做自定义监控项的时候&#xff0c;一个一个取比较麻烦&#xff0c;取出一个数值&#xff0c;就要把该数值相关信息以一定格式写入/etc/zabbix/zabbix_agentd.d/下的配置文件里&#xff0c;当遇到需要取很多数值的时候&#xff0c;这样的操作会很繁琐&#xff0c;当有一种…

前端程序员必须要知道的跨域问题以及解决方法

大厂面试题分享 面试题库 前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 前言 前端程序员必须要知道的跨域问题以及解决方法 node 代理 原理 同源策略发生在浏览…

基于Java+socket实现多线程聊天室-控制台版

基于Javasocket实现多线程聊天室-控制台版 一、系统介绍二、功能展示1.运行效果 三、代码展示四、其它1.其他系统实现2.获取源码 一、系统介绍 首先启动server端&#xff0c;然后启动client端。任意一个client发送给server的消息都将会被转发给所有在线的client&#xff0c;实…

C++基础(16)——STL常用算法(排序、拷贝和集合)

前言 本文介绍了C中STL常用排序、拷贝和集合算法 9.3&#xff1a;常见的排序算法&#xff08;sort、random_shuffle、merge、reverse&#xff09; 9.3.1&#xff1a;sort 9.3.2&#xff1a;random_shuffle 将容器中的数据位置重新打乱&#xff0c;可以配合随机数种子使用 9…

【Java】Java核心要点总结 69

文章目录 1. BIO NIO AIO2. 多线程3. 线程的生命周期和状态4. sleep() ⽅法和 wait() ⽅法对比5. 为什么 wait() ⽅法不定义在 Thread 中&#xff1f; 1. BIO NIO AIO 在Java中&#xff0c;BIO、NIO和AIO是针对网络编程的不同I/O模型&#xff1a; BIO&#xff08;Blocking I/O…

【kotlin】使用MPAndroidChart实现PieChart(饼图)并设置每个数据的颜色、标签等属性

概述 MPAndroidChart 是 Android 上一个非常流行的开源图表库&#xff0c;它提供了多种类型的图表&#xff0c;包括折线图、柱状图、饼图等。 MPAndroidChart 实现饼图 下面是一个使用 MPAndroidChart 实现饼图的示例代码&#xff1a; 首先&#xff0c;需要在项目的 build.…