Android StateLayout状态页
文章目录
- Android StateLayout状态页
- 概述
- 源码
- 使用
- 源码下载
Android StateLayout状态页
概述
StateLayout(状态页)包含:加载中页面,错误页面,空页面,内含状态默认页面,支持自定义页面。

源码
全局配置:
package com.example.tools.state_layout.widgetsimport android.view.View
import androidx.annotation.LayoutRes/*** StateLayout全局配置*/
object StateConfig {@LayoutRes@JvmStaticvar emptyLayoutRes = View.NO_ID@LayoutRes@JvmStaticvar errorLayoutRes = View.NO_ID@LayoutRes@JvmStaticvar loadingLayoutRes = View.NO_ID@LayoutRes@JvmStaticvar retryIds: IntArray? = nullprivate var mOnStateChangeListener: OnStateChangeListener? = nullfun setOnStateChangeListener(listener: OnStateChangeListener) {mOnStateChangeListener = listener}fun getOnStateChangeListener(): OnStateChangeListener? {return mOnStateChangeListener}
}
状态监听:
interface OnStateChangeListener {fun showState(status: Int)
}
属性:
<declare-styleable name="StateLayout"><attr name="empty_layout" format="reference" /><attr name="loading_layout" format="reference" /><attr name="error_layout" format="reference" />
</declare-styleable>
代码:
class StateLayout @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {companion object {const val STATE_LOADING = 0xA001const val STATE_EMPTY = 0xA002const val STATE_ERROR = 0xA003const val STATE_CONTENT = 0xA004}// empty布局资源@LayoutResprivate var emptyLayoutRes = View.NO_IDget() = if (field == View.NO_ID) StateConfig.emptyLayoutRes else field// loading布局资源@LayoutResprivate var loadingLayoutRes = View.NO_IDget() = if (field == View.NO_ID) StateConfig.loadingLayoutRes else field// error布局资源@LayoutResprivate var errorLayoutRes = View.NO_IDget() = if (field == View.NO_ID) StateConfig.errorLayoutRes else field// 保存状态private val stateInfoMap = ArrayMap<Int, View>()// 当前状态private var currentState = STATE_CONTENT// 需要设置点击事件的idprivate var retryIds: IntArray? = nullget() = field ?: StateConfig.retryIdsprivate var mOnStateChangeListener: OnStateChangeListener? = nullget() = field ?: StateConfig.getOnStateChangeListener()init {val a: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.StateLayout)emptyLayoutRes = a.getResourceId(R.styleable.StateLayout_empty_layout, View.NO_ID)loadingLayoutRes = a.getResourceId(R.styleable.StateLayout_loading_layout, View.NO_ID)errorLayoutRes = a.getResourceId(R.styleable.StateLayout_error_layout, View.NO_ID)a.recycle()}override fun onFinishInflate() {super.onFinishInflate()if (childCount != 1) {throw IllegalStateException("StateLayout必须只能有一个子View")}if (stateInfoMap.size == 0) {val view = getChildAt(0)setContentView(view)}}/*** 设置内容布局*/private fun setContentView(contentView: View) {stateInfoMap[STATE_CONTENT] = contentView}/*** 设置点击事件*/fun setRetryIds(@IdRes vararg ids: Int) {retryIds = ids}/*** 设置状态变化监听*/fun setOnStateChangeListener(listener: OnStateChangeListener) {mOnStateChangeListener = listener}/*** 显示内容布局*/fun showContent() {showState(STATE_CONTENT)}/*** 显示加载布局*/fun showLoading() {showState(STATE_LOADING)}/*** 显示失败布局*/fun showError() {showState(STATE_ERROR)}/*** 显示空布局*/fun showEmpty() {showState(STATE_EMPTY)}/*** 显示视图*/private fun showState(status: Int) {if (currentState == status) {return}val stateView = getStateView(status)for (i in stateInfoMap) {if (i.key != status) {val view = i.valuehideStateView(view)}}showStateView(this, stateView, status)mOnStateChangeListener?.showState(status)currentState = status}/*** 获取状态视图*/private fun getStateView(status: Int): View {val view = stateInfoMap[status]if (view != null) {return view} else {val layoutRes = when (status) {STATE_EMPTY -> emptyLayoutResSTATE_ERROR -> errorLayoutResSTATE_LOADING -> loadingLayoutResSTATE_CONTENT -> View.NO_IDelse -> View.NO_ID}if (layoutRes == View.NO_ID) {when (status) {STATE_ERROR -> throw Resources.NotFoundException("请设置errorLayout")STATE_EMPTY -> throw Resources.NotFoundException("请设置emptyLayout")STATE_LOADING -> throw Resources.NotFoundException("请设置loadingLayout")STATE_CONTENT -> throw Resources.NotFoundException("请设置contentView")}}val view = LayoutInflater.from(context).inflate(layoutRes, this, false)stateInfoMap[status] = viewreturn view}}/*** 隐藏视图*/private fun hideStateView(view: View) {view.visibility = View.GONE}/*** 显示视图*/private fun showStateView(container: StateLayout, view: View, status: Int) {if (container.indexOfChild(view) != -1) {view.visibility = View.VISIBLE} else {if (status == STATE_EMPTY || status == STATE_ERROR) {if (retryIds != null) {for (id in retryIds!!) {view.findViewById<View>(id).setOnClickListener {showLoading()}}}}container.addView(view)}}
}
使用
使用全局配置:
<com.example.tools.state_layout.widgets.StateLayoutandroid:id="@+id/state_layout"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="加载成功" />
</com.example.tools.state_layout.widgets.StateLayout>
StateConfig.emptyLayoutRes = R.layout.state_empty
StateConfig.errorLayoutRes = R.layout.state_error
StateConfig.loadingLayoutRes = R.layout.state_loading
StateConfig.retryIds = intArrayOf(R.id.state_msg, R.id.state_iv)StateConfig.setOnStateChangeListener(object : OnStateChangeListener {override fun showState(status: Int) {when (status) {StateLayout.STATE_LOADING -> {LogUtils.e("StateLayout", "显示加载页")postDelayed({stateLayout.showContent()}, 2000L)}StateLayout.STATE_CONTENT -> {LogUtils.e("StateLayout", "显示内容页")}StateLayout.STATE_ERROR -> {LogUtils.e("StateLayout", "显示失败页")}StateLayout.STATE_EMPTY -> {LogUtils.e("StateLayout", "显示空页")}}}
})
使用局部配置:
<com.example.tools.state_layout.widgets.StateLayoutandroid:id="@+id/state_layout"android:layout_width="match_parent"android:layout_height="match_parent"app:empty_layout="@layout/state_empty"app:error_layout="@layout/state_error"app:loading_layout="@layout/state_loading"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="加载成功" />
</com.example.tools.state_layout.widgets.StateLayout>
stateLayout.setRetryIds(R.id.state_msg, R.id.state_iv)
stateLayout.setOnStateChangeListener(object : OnStateChangeListener {override fun showState(status: Int) {when (status) {StateLayout.STATE_LOADING -> {LogUtils.e("StateLayout", "显示加载页")postDelayed({stateLayout.showContent()}, 2000L)}StateLayout.STATE_CONTENT -> {LogUtils.e("StateLayout", "显示内容页")}StateLayout.STATE_ERROR -> {LogUtils.e("StateLayout", "显示失败页")}StateLayout.STATE_EMPTY -> {LogUtils.e("StateLayout", "显示空页")}}}
})
源码下载
相关文章:
Android StateLayout状态页
文章目录 Android StateLayout状态页概述源码使用源码下载 Android StateLayout状态页 概述 StateLayout(状态页)包含:加载中页面,错误页面,空页面,内含状态默认页面,支持自定义页面。 源码 …...
JetBrains数据库驱动下载失败解决方法
本方法可通用于解决PyCharm等JetBrains家的IDE下载数据库驱动问题。 在Jet家IDE内连接数据库时,mysql、sqlite等的驱动有部分在 https://download.jetbrains.com 网站上,可能由于网络问题无法访问。 解决方法是修改 JetBrains 路径下的 jdbc.drivers.xm…...
【vim 学习系列文章 16 -- vim 自动保存设置】
文章目录 vim 自动保存设置 vim 自动保存设置 在 Vim 编辑器中,你可以通过设置 updatetime 选项来控制自动保存的时间间隔。updatetime 的默认值是 4000 毫秒(4 秒),但你可以将其设置为 5000 毫秒(5 秒)以…...
python的O2O生鲜食品订购flask-django-nodejs-php
用户只能通过一些类似软件进行查看生鲜超市,这样的管理方式仍然是比较机械传统的,本文通过对市面上常见的线上管理系统与现实生活中结合问题的讨论,从一个微信小程序的O2O生鲜食品订购角度进行需求分析,提供一些新的思路ÿ…...
六、大模型-Prompt-API介绍
GPT-3.5 API 提供了一个名为 openai.ChatCompletion.create() 的端点,您可以使用该端点来与 ChatGPT 进行交互。以下是 openai.ChatCompletion.create() 的详细 API 说明: 请求参数: messages:一个数组,包含对话中的消…...
嵌入式安全性基础知识-计算机系统安全知识+信息安全基础+网络安全协议-嵌入式系统设计师备考笔记
0、前言 本专栏为个人备考软考嵌入式系统设计师的复习笔记,未经本人许可,请勿转载,如发现本笔记内容的错误还望各位不吝赐教(笔记内容可能有误怕产生错误引导)。 本章的主要内容见下图: 1、计算机系统系统…...
基于javaSpringboot+mybatis+layui的装修验收管理系统设计和实现
基于javaSpringbootmybatislayui的装修验收管理系统设计和实现 博主介绍:多年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留…...
jenkins构建完成后部署到本机,无法读取容器外文件夹
项目背景: Dockerjenkins 构建完成后,要把打包的dist文件夹内容移动到网站目录 /www/wwwroot/xxxxxx 文件夹下;但是获取不到jenkins容器外的文件夹。 解决办法: 在容器中,添加挂载/映射本机目录,把网站…...
如何使用 Elasticsearch 作为向量数据库
在今天的文章中,我们将很快地通过 Docker 来快速地设置 Elasticsearch 及 Kibana,并设置 Elasticsearch 为向量搜索。 拉取 Docker 镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:8.12.2 docker pull docker.elastic.co/kibana/kiba…...
高精度AI火灾烟雾检测算法,助力打造更加安全的楼宇环境
一、方案背景 近日,南京居民楼火灾事故导致15人死亡的新闻闹得沸沸扬扬,这一事件又激起了大家对楼宇火灾隐患的进一步担忧。事后我们除了思考政府、消防及物业部门应对此事的解决办法,我们还应该思考如何利用现有的技术帮助人们减少此类事情的…...
node和npm yarn包管理工具
node和包管理工具 今日目标: 1.dos常用指令 2.node的模块化 3.npm包管理工具 4.yarn的常用指令 5.node的内置模块 00-回顾 # Promose:作用:解决ajax请求响应顺序不可控的问题特性:1. Promise是一个构造函数,需要通过new关…...
鸿蒙Harmony应用开发—ArkTS(@Link装饰器:父子双向同步)
子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。 说明: 从API version 9开始,该装饰器支持在ArkTS卡片中使用。 概述 Link装饰的变量与其父组件中的数据源共享相同的值。 限制条件 Link装饰器不能在Entry装饰的自定义组件中使用…...
【数据结构】猛猛干7道链表OJ
前言知识点 链表的调试技巧 int main() {struct ListNode* n1(struct ListNode*)malloc(sizeof(struct ListNode));assert(n1);struct ListNode* n2(struct ListNode*)malloc(sizeof(struct ListNode));assert(n2);struct ListNode* n3(struct ListNode*)malloc(sizeof(struc…...
记录C++中,子类同名属性并不能完全覆盖父类属性的问题
问题代码: 首先看一段代码:很简单,就是BBB继承自AAA,然后BBB重写定义了同名属性,然后调用父类AAA的打印函数: #include <iostream> using namespace std;class AAA { public:AAA() {}~AAA() {}void …...
使用 ONLYOFFICE API 构建 Java 转换器,在 Word 和 PDF 之间进行转换
文章作者:ajun 随着文档处理需求的增加,格式转换成为了一个重要的需求点。由于PDF格式具有跨平台、不易被篡改的特性,将Word格式(.docx)转换为PDF格式(.pdf)的需求尤为强烈。ONLYOFFICE作为一个强大的办公套件,提供了这样的转换功…...
SpringCloudAlibaba Nacos配置及应用
Nacos搭建及配置 nacos本机服务搭建 windows上搭建单机nacos: Releases alibaba/nacos GitHub 下载安装包 下载本地,解压,直接运行(保证安装包的绝度路径只有英文字符,有中文会导致运行失败)ÿ…...
#Linux(权限管理)
(一)发行版:Ubuntu16.04.7 (二)记录: (1) (2)-开头代表普通文件 划分为三组: rw- rw- r-- rw-: 文件拥有…...
easyExcel复杂表头导出
代码 import com.alibaba.excel.EasyExcel; import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;import java.util.ArrayList; import java.util.Arrays; imp…...
【大数据】五、yarn基础
Yarn Yarn 是用来做分布式系统中的资源协调技术 MapReduce 1.x 对于 MapReduce 1.x 的版本上: 由 Client 发起计算请求,Job Tracker 接收请求之后分发给各个TaskTrack进行执行 在这个阶段,资源的管理与请求的计算是集成在 mapreduce 上的…...
语义分割实战项目(从原理到代码环境配置)
语义分割(Semantic Segmentation) 先看结果: 是计算机视觉和深度学习领域的一项核心任务,它主要致力于对图像中的每一个像素进行分类,赋予每个像素一个类别标签,以达到理解图像内容的目的。换句话说&#…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...
