Android drawable level-list XML实现电量或信号图标变化

煙雲

煙雲

2026-03-20

734人浏览

原创

level-list 是基于 android:level 值动态切换 drawable 的资源类型;它按数值区间匹配 item,而 state-list 仅响应状态变化,不支持 level 属性,误用会导致 ui 不更新或只显示首项。

android drawable level-list xml实现电量或信号图标变化

level-list 是什么,为什么不能直接用 state-list

它不是用来响应按钮点击或焦点变化的,而是靠 android:level 值动态切换子项——比如电量从 0 到 100,你给每个区间配一个 item,系统根据 level 自动选中匹配的 drawable。state-list 只认状态(android:state_pressed 这类),不认数值,硬塞 level 会完全没反应。

常见错误现象:ImageView 死活不换图,或者只显示第一个 item;debug 时发现 setImageLevel() 调了但 UI 没变——大概率是 XML 里没写 android:maxLevel,或 Java/Kotlin 里传的 level 超出范围(0–10000 是合法范围,但你的 item 只定义了 0–4)。

  • 每个 itemandroid:maxLevelandroid:minLevel 必须覆盖连续整数区间,比如 0–20、21–40、41–60…不能留空档,也不能重叠
  • level-list 根节点的 android:constantSize="true" 推荐加上,否则每次 level 变化时,intrinsic size 可能抖动(尤其嵌套在 TextView 的 compound drawable 里)
  • Android 旧版本(animateLevelChange() 在所有机型上都丝滑

XML 里怎么写 level 区间才不踩坑

别按百分比写死 0–25、26–50…实际用电池 API 拿到的是整数(如 Intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)),而 level-list 的 level 值默认是 0–10000 映射,所以更稳妥的做法是把原始值放大 100 倍再设,让区间对齐整数边界。

示例:电量图标分 5 档(0%、20%、40%、60%、80%+),对应 level 值 0、2000、4000、6000、8000:

<level-list xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/ic_battery_0" android:minlevel="0" android:maxlevel="1999"></item><item android:drawable="@drawable/ic_battery_20" android:minlevel="2000" android:maxlevel="3999"></item><item android:drawable="@drawable/ic_battery_40" android:minlevel="4000" android:maxlevel="5999"></item><item android:drawable="@drawable/ic_battery_60" android:minlevel="6000" android:maxlevel="7999"></item><item android:drawable="@drawable/ic_battery_80" android:minlevel="8000" android:maxlevel="10000"></item></level-list>
  • 所有 minLevel/maxLevel 必须是整数,小数会被截断(写 20.5 等于写 20)
  • 最后一个 item 的 maxLevel 建议设为 10000,避免 level 略超预期(比如 101%)导致 fallback 到第一个 item
  • 资源名别带中文或空格,@drawable/ic_battery_100% 这种会编译失败

Java/Kotlin 里怎么安全设置 level

直接调 setImageLevel() 不行——如果 ImageView 的 drawable 不是 level-list 类型,会静默失败;而且 level 值没做校验,传负数或超大数可能触发异常或显示错乱。

正确做法:先取 drawable,强转成 LevelListDrawable,再 setLevel,并确保在主线程执行:

val drawable = imageView.drawable
if (drawable is LevelListDrawable) {
    val level = (batteryPercent * 100).coerceAtMost(10000)
    drawable.level = level
}
  • 必须检查类型,imageView.getDrawable() 返回的是 Drawable,不是所有 drawable 都支持 level
  • level 值建议用 coerceAtMost(10000)clamp(0, 10000) 限制范围,别信外部数据源
  • 如果用在 RecyclerView 里,记得在 onBindViewHolder 中每次都重新 setLevel,因为 ViewHolder 复用会导致 level 残留

信号强度场景下 level-list 的特殊处理

信号强度(TelephonyManager.getSignalStrength())返回的是 ASU 值(通常 0–31),和电量不同,它没有标准百分比映射。硬套 0–31 到 level 0–10000 会导致图标切换生硬——比如 ASU=12 和 ASU=13 在视觉上几乎没差别,但 level 差 323,可能跨两个 item。

更合理的做法是做离散映射:把 ASU 分成 4–5 档(差、弱、中、强、满),每档对应一个固定 level 值(如 0、2500、5000、7500、10000),再查表转换:

private fun asuToLevel(asu: Int): Int = when (asu) {
    in 0..5 -> 0
    in 6..12 -> 2500
    in 13..18 -> 5000
    in 19..25 -> 7500
    else -> 10000
}
  • 别用线性缩放,ASU 和实际信号质量不是正比关系
  • 注意不同制式(LTE/5G)ASU 范围不同,有些设备 LTE 下 ASU 最高是 97,得适配
  • 如果用 SignalStrengthgetLevel()(返回 0–4),反而更简单——直接乘 2500 就行,但要注意这个 level 是系统估算值,不一定准

level-list 看似简单,真正难的是 level 值的来源是否稳定、区间划分是否符合人眼感知、以及复用场景下的状态清理——这些地方一漏,图标就卡在某一级不动了。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Kotlin协程编程与Spring Boot集成实践
Kotlin协程编程与Spring Boot集成实践

本专题围绕 Kotlin 协程机制展开,深入讲解挂起函数、协程作用域、结构化并发与异常处理机制,并结合 Spring Boot 展示协程在后端开发中的实际应用。内容涵盖异步接口设计、数据库调用优化、线程资源管理以及性能调优策略,帮助开发者构建更加简洁高效的 Kotlin 后端服务架构。

2026.02.12

227

18

Java Kotlin协程与异步编程实战
Java Kotlin协程与异步编程实战

本专题围绕 Kotlin 协程与异步编程展开,讲解挂起函数、协程作用域、异步任务调度及并发控制方法。通过实际项目案例,帮助开发者提升后端服务性能,实现高效异步任务处理与稳定性保障。

2026.04.13

53

16

Kotlin Android开发教程大全
Kotlin Android开发教程大全

系统讲解 Google 官方推荐的 Android 开发首选语言 Kotlin 的核心知识与工程实践,涵盖 Kotlin 简洁语法(空安全/数据类/扩展函数/解构声明/作用域函数)与 Java 互操作、集合操作与函数式编程、协程(Coroutines)异步编程(suspend/launch/async/Flow)、Jetpack Compose 声明式 UI 开发(状态管理/组合函数/导航/动画)、MVVM / MVI 架构设计与 Vi

2026.06.03

81

19

pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.01

2783

5

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

2024.08.01

3363

7

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

2024.11.28

1793

7

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

2070

6

android开发三大框架
android开发三大框架

android开发三大框架是XUtil框架、volley框架、ImageLoader框架。本专题为大家提供android开发三大框架相关的各种文章、以及下载和课程。

2023.08.14

753

4

android是什么系统
android是什么系统

Android是一种功能强大、灵活可定制、应用丰富、多任务处理能力强、兼容性好、网络连接能力强的操作系统。本专题为大家提供android相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.22

2058

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.4万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 131.8万人学习