一颗小红星 發表於 2025-9-23 10:33:00

Android自定义电池组件实例代码(BatteryView)

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>支持:</li><li>1、自定义属性res/values/attrs.xml</li><li>2、 组件代码BatteryView.kt</li><li>3、XML 用法示例</li><li>4、代码控制示例</li><li>5、常见问题(结合你之前的疑问)</li><li>6、小扩展(可选)</li></ul></div><p class="maodian"></p><h2>支持:</h2>
<blockquote><ul><li><p>XML 与代码动态设置电量(0&ndash;100)</p></li><li><p>充电&nbsp;<code>charging</code>&nbsp;与快充&nbsp;<code>fastCharging</code>&nbsp;区分(闪电样式 + 动画)</p></li><li><p>电量阈值自动配色:&lt;20% 红、&lt;50% 橙、&ge;50% 绿</p></li><li><p>可配置边框/轨道/电量/闪电颜色;可显示百分比文本</p></li><li><p>支持无障碍(contentDescription、AccessibilityLiveRegion)</p></li><li><p>支持状态保存(旋转/进程重建)</p></li><li><p>平滑动画过渡(setLevelAnimated)</p></li></ul></blockquote>
<p class="maodian"></p><h2>1、自定义属性res/values/attrs.xml</h2>
<div class="jb51code"><pre class="brush:xml;">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;resources&gt;
&lt;declare-styleable name="BatteryView"&gt;
&lt;attr name="bv_level" format="integer"/&gt;
&lt;attr name="bv_showPercentage" format="boolean"/&gt;
&lt;attr name="bv_charging" format="boolean"/&gt;
&lt;attr name="bv_fastCharging" format="boolean"/&gt;

&lt;attr name="bv_borderColor" format="color"/&gt;
&lt;attr name="bv_trackColor" format="color"/&gt;
&lt;attr name="bv_fillColor" format="color"/&gt;
&lt;attr name="bv_lowColor" format="color"/&gt;
&lt;attr name="bv_mediumColor" format="color"/&gt;
&lt;attr name="bv_highColor" format="color"/&gt;
&lt;attr name="bv_boltColor" format="color"/&gt;

&lt;attr name="bv_borderWidth" format="dimension"/&gt;
&lt;attr name="bv_cornerRadius" format="dimension"/&gt;
&lt;attr name="bv_capWidth" format="dimension"/&gt;
&lt;attr name="bv_capGap" format="dimension"/&gt;
&lt;attr name="bv_textSize" format="dimension"/&gt;
&lt;/declare-styleable&gt;
&lt;/resources&gt;</pre></div>
<p>术语说明:</p>
<ul><li><p><strong>borderColor</strong>:电池外框线条颜色。</p></li><li><p><strong>trackColor</strong>:电池内部&ldquo;轨道/背景&rdquo;颜色(未被电量填充区域)。</p></li><li><p><strong>fillColor</strong>:电量填充的基础颜色(当未启用分段阈值或外部强制指定时)。</p></li></ul>
<p class="maodian"></p><h2>2、 组件代码BatteryView.kt</h2>
<div class="jb51code"><pre class="brush:java;">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 -&gt; "(快充中)"
charging -&gt; "(充电中)"
else -&gt; ""
}
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&lt;SavedState&gt; = object : Parcelable.Creator&lt;SavedState&gt; {
override fun createFromParcel(source: Parcel): SavedState = SavedState(source)
override fun newArray(size: Int): Array&lt;SavedState?&gt; = arrayOfNulls(size)
}
}
}
// endregion

// region — Utils
private fun dp(v: Float) = v * resources.displayMetrics.density
private fun sp(v: Float) = v * resources.displayMetrics.scaledDensity
// endregion
}</pre></div>
<p class="maodian"></p><h2>3、XML 用法示例</h2>
<div class="jb51code"><pre class="brush:xml;">&lt;com.yourpkg.widget.BatteryView
android:id="@+id/battery"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_margin="16dp"
app:bv_level="45"
app:bv_showPercentage="true"
app:bv_charging="true"
app:bv_fastCharging="false"

app:bv_borderColor="#222222"
app:bv_trackColor="#F2F2F2"
app:bv_lowColor="#E53935"
app:bv_mediumColor="#FB8C00"
app:bv_highColor="#43A047"
app:bv_boltColor="#FFFFFF"

app:bv_borderWidth="2dp"
app:bv_cornerRadius="8dp"
app:bv_capWidth="7dp"
app:bv_capGap="2dp"
app:bv_textSize="12sp"/&gt;</pre></div>
<p class="maodian"></p><h2>4、代码控制示例</h2>
<div class="jb51code"><pre class="brush:java;">val bv = findViewById&lt;BatteryView&gt;(R.id.battery)

// 动态设置电量
bv.level = 18 // 立即刷新
bv.setLevelAnimated(76) // 平滑动画到 76%

// 充电状态
bv.charging = true // 显示闪电 + 呼吸动画
bv.fastCharging = true // 闪电更大、视觉更强

// 开关百分比
bv.showPercentage = false

// 结合业务:阈值配色自动处理(&lt;20 红、&lt;50 橙、≥50 绿),无需额外代码</pre></div>
<p class="maodian"></p><h2>5、常见问题(结合你之前的疑问)</h2>
<ul><li><p><strong>Q:&nbsp;</strong><code>borderColor</code><strong>&nbsp;和&nbsp;</strong><code>trackColor</code><strong>&nbsp;是什么?</strong><br />A:&nbsp;<code>borderColor</code>&nbsp;是外框线条;<code>trackColor</code>&nbsp;是内部未充满的背景。</p></li><li><p><strong>Q: 无障碍报错&nbsp;</strong><code>isImportantForAccessibility</code><strong>?</strong><br />A: 组件内已设置:</p>
<p>importantForAccessibility&nbsp;=&nbsp;View.IMPORTANT_FOR_ACCESSIBILITY_YES</p>
<p>accessibilityLiveRegion&nbsp;=&nbsp;View.ACCESSIBILITY_LIVE_REGION_POLITE</p>
<p>同时动态更新&nbsp;<code>contentDescription</code>,读屏会播报&ldquo;电量 76%,快充中&rdquo;。</p></li><li><p><strong>Q: 如何自定义颜色?</strong><br />在 XML 传入&nbsp;<code>bv_lowColor/bv_mediumColor/bv_highColor</code>,或在代码里直接修改。</p></li><li><p><strong>Q: 性能如何?</strong><br />组件绘制简单,动画为轻量级呼吸,<code>postOnAnimation</code>&nbsp;驱动,开销极低。</p></li></ul>
<p class="maodian"></p><h2>6、小扩展(可选)</h2>
<ul><li><p>电量渐变色:将&nbsp;<code>fillPaint</code>&nbsp;设置为&nbsp;<code>LinearGradient</code>,根据 level 动态改变 endX。</p></li><li><p>低电量闪烁:level&lt;10 且非充电时,使用&nbsp;<code>alpha</code>&nbsp;在 120&ndash;255 之间脉动。</p></li><li><p>RTL 适配:当&nbsp;<code>layoutDirection == LAYOUT_DIRECTION_RTL</code>&nbsp;时从右向左填充(可根据需要调整&nbsp;<code>fillRect</code>&nbsp;计算)。</p></li></ul>
<p>到此这篇关于Android自定义电池组件(BatteryView)的文章就介绍到这了,更多相关Android自定义电池组件内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Android实现侦听电池状态显示、电量及充电动态显示的方法</li><li>Android获取手机电池电量用法实例</li><li>Android中获取电池电量实例代码</li><li>获取Android设备电池电量状态</li><li>Android电池电量监听的示例代码</li><li>Android电池电量跳变</li><li>Android监听电池状态实例代码</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: Android自定义电池组件实例代码(BatteryView)