完整教程:Android 自定义电池组件(BatteryView)
2025-09-22 16:03 tlnshuju 阅读(0) 评论(0) 收藏 举报支持:
XML 与代码动态设置电量(0–100)
充电
charging
与快充fastCharging
区分(闪电样式 + 动画)电量阈值自动配色:<20% 红、<50% 橙、≥50% 绿
可配置边框/轨道/电量/闪电颜色;可显示百分比文本
支持无障碍(contentDescription、AccessibilityLiveRegion)
支持状态保存(旋转/进程重建)
平滑动画过渡(setLevelAnimated)
1、自定义属性 res/values/attrs.xml
术语说明:
borderColor:电池外框线条颜色。
trackColor:电池内部“轨道/背景”颜色(未被电量填充区域)。
fillColor:电量填充的基础颜色(当未启用分段阈值或外部强制指定时)。
2、 组件代码 BatteryView.kt
package com.yourpkg.widget
val y6 = t + h * 0.35f
boltPath.reset()
boltPath.moveTo(x1, y1)
boltPath.lineTo(x2, y2)
boltPath.lineTo(x3, y3)
boltPath.lineTo(x4, y4)
boltPath.lineTo(x5, y5)
boltPath.lineTo(x6, y6)
boltPath.close()
}
// endregion
// region — Accessibility
private fun updateContentDesc() {
val charge = when {
fastCharging -> "(快充中)"
charging -> "(充电中)"
else -> ""
}
contentDescription = "电量 $level%$charge"
}
// endregion
// region — State
override fun onSaveInstanceState(): Parcelable? {
val superState = super.onSaveInstanceState()
return SavedState(superState).also {
it.level = level
it.charging = charging
it.fastCharging = fastCharging
it.showPercentage = showPercentage
it.chargePulse = chargePulse
}
}
override fun onRestoreInstanceState(state: Parcelable?) {
val ss = state as? SavedState
super.onRestoreInstanceState(ss?.superState ?: state)
ss?.let {
level = it.level
charging = it.charging
fastCharging = it.fastCharging
showPercentage = it.showPercentage
chargePulse = it.chargePulse
toggleChargeAnim(charging)
}
}
private class SavedState : BaseSavedState {
var level: Int = 0
var charging: Boolean = false
var fastCharging: Boolean = false
var showPercentage: Boolean = false
var chargePulse: Float = 0f
constructor(superState: Parcelable?) : super(superState)
private constructor(inParcel: Parcel) : super(inParcel) {
level = inParcel.readInt()
charging = inParcel.readInt() == 1
fastCharging = inParcel.readInt() == 1
showPercentage = inParcel.readInt() == 1
chargePulse = inParcel.readFloat()
}
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
out.writeInt(level)
out.writeInt(if (charging) 1 else 0)
out.writeInt(if (fastCharging) 1 else 0)
out.writeInt(if (showPercentage) 1 else 0)
out.writeFloat(chargePulse)
}
companion object {
@JvmField val CREATOR: Parcelable.Creator = object : Parcelable.Creator {
override fun createFromParcel(source: Parcel): SavedState = SavedState(source)
override fun newArray(size: Int): Array = arrayOfNulls(size)
}
}
}
// endregion
// region — Utils
private fun dp(v: Float) = v * resources.displayMetrics.density
private fun sp(v: Float) = v * resources.displayMetrics.scaledDensity
// endregion
}
3、XML 用法示例
4、代码控制示例
val bv = findViewById(R.id.battery)
// 动态设置电量
bv.level = 18 // 立即刷新
bv.setLevelAnimated(76) // 平滑动画到 76%
// 充电状态
bv.charging = true // 显示闪电 + 呼吸动画
bv.fastCharging = true // 闪电更大、视觉更强
// 开关百分比
bv.showPercentage = false
// 结合业务:阈值配色自动处理(<20 红、<50 橙、≥50 绿),无需额外代码
5、常见问题(结合你之前的疑问)
Q:
borderColor
和trackColor
是什么?
A:borderColor
是外框线条;trackColor
是内部未充满的背景。Q: 无障碍报错
isImportantForAccessibility
?
A: 组件内已设置:importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE
同时动态更新
contentDescription
,读屏会播报“电量 76%,快充中”。Q: 如何自定义颜色?
在 XML 传入bv_lowColor/bv_mediumColor/bv_highColor
,或在代码里直接修改。Q: 性能如何?
组件绘制简单,动画为轻量级呼吸,postOnAnimation
驱动,开销极低。
6、小扩展(可选)
电量渐变色:将
fillPaint
设置为LinearGradient
,根据 level 动态改变 endX。低电量闪烁:level<10 且非充电时,使用
alpha
在 120–255 之间脉动。RTL 适配:当
layoutDirection == LAYOUT_DIRECTION_RTL
时从右向左填充(可根据需要调整fillRect
计算)。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909576.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!