电池图标都是用代码画出来的,不管是statusbar还是settings->battery里面的都是。都是使用BatteryMeterView这个类实现的,只是statusbar和settings里面分别为不同的BatteryMeterView。BatteryMeterView里面会有一个ThemedBatteryDrawable类型的drawable,就是用这个来画电池图标的。所以直接修改这个ThemedBatteryDrawable.kt,就可以同时改变statusbar和settings中的电池图标了。
ThemedBatteryDrawable 就是加载了一些电池图标的路径,然后绘制出来。
这里贴一些主要代码,这个就是去加载电池绘制的路径。
private fun loadPaths() {
val pathString = context.resources.getString(
com.android.internal.R.string.config_batterymeterPerimeterPath)
perimeterPath.set(PathParser.createPathFromPathData(pathString))
perimeterPath.computeBounds(RectF(), true)
val errorPathString = context.resources.getString(
com.android.internal.R.string.config_batterymeterErrorPerimeterPath)
errorPerimeterPath.set(PathParser.createPathFromPathData(errorPathString))
errorPerimeterPath.computeBounds(RectF(), true)
val fillMaskString = context.resources.getString(
com.android.internal.R.string.config_batterymeterFillMask)
fillMask.set(PathParser.createPathFromPathData(fillMaskString))
......
}
路径在frameworks/base/core/core/res/res/values/config.xml中
config_batterymeterPerimeterPath 电池外框,空心的
config_batterymeterErrorPerimeterPath 电池外框,空心的,这个用来画battery saver模式的外框,路径一样只是颜色不一样
config_batterymeterFillMask 电池内框,就是电量
config_batterymeterBoltPath 闪电,充电的
config_batterymeterPowersavePath 加号
M3.5,2 v0 H1.33 C0.6,2 0,2.6 0,3.33 V13v5.67 C0,19.4 0.6,20 1.33,20 h9.33 C11.4,20 12,19.4 12,18.67 V13V3.33 C12,2.6 11.4,2 10.67,2 H8.5 V0 H3.5 z M2,18v-7V4h8v9v5H2L2,18z
@string/config_batterymeterPerimeterPath
M2,18 v-14 h8 v14 z
M5,17.5 V12 H3 L7,4.5 V10 h2 L5,17.5 z
M9,10l-2,0l0,-2l-2,0l0,2l-2,0l0,2l2,0l0,2l2,0l0,-2l2,0z
你可以把这些路径放在android studio中的vector中,看看它们长什么样子。
下面就是去画电池
override fun draw(c: Canvas) {
c.saveLayer(null, null)
unifiedPath.reset()
levelPath.reset()
levelRect.set(fillRect)
val fillFraction = batteryLevel / 100f
val fillTop =
if (batteryLevel >= 95)
fillRect.top
else
fillRect.top + (fillRect.height() * (1 - fillFraction))
levelRect.top = Math.floor(fillTop.toDouble()).toFloat()
levelPath.addRect(levelRect, Path.Direction.CCW)
// The perimeter should never change
unifiedPath.addPath(scaledPerimeter)
// If drawing dual tone, the level is used only to clip the whole drawable path
if (!dualTone) {
unifiedPath.op(levelPath, Path.Op.UNION)
}
fillPaint.color = levelColor
// Deal with unifiedPath clipping before it draws
if (charging) {
// Clip out the bolt shape
unifiedPath.op(scaledBolt, Path.Op.DIFFERENCE)
if (!invertFillIcon) {
c.drawPath(scaledBolt, fillPaint)
}
}
电量:更具电量,确定levelpath的高度,它是一个rect
path.op() 这个用来抠图,或画图。 Path.Op.UNION 就是把2个路径重合,取合集,就是会把2个路径都画出来,重合的地方也画。Path.Op.DIFFERENCE就是把2个路径不一样的地方画出来,重合的地方不画。
关于怎么设置路径,你可以先在androidstudio中创建vector assest,然后自己试试看效果,最后把路径加到代码中。
你也可以在网上找矢量图,然后转换为vector,如果网上的图片路径太大,你可以看看这个https://blog.csdn.net/Aaron121314/article/details/106070330 怎么去把路径缩小,改变图片位置。直接修改路径不显示,太复杂了,除非是简单的图片。