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) 先看结果: 是计算机视觉和深度学习领域的一项核心任务,它主要致力于对图像中的每一个像素进行分类,赋予每个像素一个类别标签,以达到理解图像内容的目的。换句话说&#…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
