最近产品研发需求需要显示在线设备的电池电量状态,然后UI给出的效果的图是这样的
于是就开始了自定义个,因为是项目特定的UI所以很多属性都没有直接抽取到styles里面了,直接上代码(因为项目是使用kotlin的,所以直接用kotlin进行编程了,当然也附带了Java版本的)
kotlin版本(里面用到的颜色值可自定义,这里是使用项目工具类转过来的):
package com.view
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
import com.blankj.utilcode.util.ColorUtils
import com.blankj.utilcode.util.ImageUtils
import com.view.R
/**
* @CreateDate:
* @Author:lp
* @Description:
*/
class BatteryView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
View(context, attrs) {
private val batteryBodyPainter: Paint//电池外边框画笔
private val batteryHeadPainter: Paint//电池盖画笔
private val mPowerPaint: Paint//电量画笔
private val outlineRect: RectF//电池矩形
private val mCapRect: RectF//电池盖矩形
private val batteryRect: RectF//电量矩形
private var fullPowerWidth = 0f //满电量时电池体的宽度。
private var battery = 20
private var leftPoint = 0f
private var topPoint = 0f
fun setBattery(battery: Int) {
this.battery = battery
invalidate()
}
fun getBattery(): Int {
return battery
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val specWidthSize = MeasureSpec.getSize(widthMeasureSpec) //宽
val specHeightSize = MeasureSpec.getSize(heightMeasureSpec) //高
//设置电池外框
outlineRect.right = specWidthSize - OUTLINE_THICKNESS - CAP_WIDTH
outlineRect.bottom = specHeightSize - OUTLINE_THICKNESS
//设置电池盖矩形
mCapRect.left = outlineRect.right
mCapRect.top = specHeightSize.toFloat() / 2 - CAP_HEIGHT / 2
mCapRect.right = specWidthSize.toFloat()
mCapRect.bottom = specHeightSize.toFloat() / 2 + CAP_HEIGHT / 2
//设置电池体
batteryRect.left = outlineRect.left + GAP_OF_SHAPE_BODY
batteryRect.top = outlineRect.top + GAP_OF_SHAPE_BODY
batteryRect.bottom = outlineRect.bottom - GAP_OF_SHAPE_BODY
//闪电位置
leftPoint = specWidthSize / 2 - OUTLINE_THICKNESS * 2
topPoint = specHeightSize / 2 - OUTLINE_THICKNESS * 2
fullPowerWidth = outlineRect.right - GAP_OF_SHAPE_BODY - batteryRect.left
setMeasuredDimension(specWidthSize, specHeightSize)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
//设置电量矩形
var batter = battery
if (batter < 0) {
batter = 50
}
batteryRect.right = batter.toFloat() / 100 * fullPowerWidth + batteryRect.left
when {
battery < 0 -> {
batteryBodyPainter.color = ColorUtils.getColor(R.color.color_818283)
batteryHeadPainter.color = ColorUtils.getColor(R.color.color_818283)
mPowerPaint.color = ColorUtils.getColor(R.color.color_818283)
}
battery <= 20 -> {
batteryBodyPainter.color = ColorUtils.getColor(R.color.color_818283)
batteryHeadPainter.color = ColorUtils.getColor(R.color.color_FF4A37)
mPowerPaint.color = ColorUtils.getColor(R.color.color_FF4A37)
}
battery <= 40 -> {
batteryBodyPainter.color = ColorUtils.getColor(R.color.color_41D9B5)
batteryHeadPainter.color = ColorUtils.getColor(R.color.color_41D9B5)
mPowerPaint.color = ColorUtils.getColor(R.color.color_FF9037)
}
else -> {
batteryBodyPainter.color = ColorUtils.getColor(R.color.color_2CBF6C)
batteryHeadPainter.color = ColorUtils.getColor(R.color.color_2CBF6C)
mPowerPaint.color = ColorUtils.getColor(R.color.color_2CBF6C)
}
}
canvas.drawRoundRect(
outlineRect,
ROUND_CORNER_RADIUS,
ROUND_CORNER_RADIUS,
batteryBodyPainter
)
canvas.drawRoundRect(mCapRect, 1f, 1f, batteryHeadPainter)
canvas.drawRoundRect(batteryRect, ROUND_CORNER_RADIUS, ROUND_CORNER_RADIUS, mPowerPaint)
if (battery in 0..20) {
val bitmap = ImageUtils.getBitmap(R.mipmap.shandian)
canvas.drawBitmap(bitmap, leftPoint, topPoint, null)
}
}
companion object {
private const val OUTLINE_THICKNESS = 3.0f //电池框厚度
private const val CAP_WIDTH = 2.0f //电池盖宽度
private const val CAP_HEIGHT = 8.0f //电池盖高度
private const val GAP_OF_SHAPE_BODY = 2.0f //电池体与外框之间的间隙
private const val ROUND_CORNER_RADIUS = 2f//电池圆角
}
init {
//电池外框
batteryBodyPainter = Paint()
batteryBodyPainter.color = ColorUtils.getColor(R.color.color_2CBF6C)
batteryBodyPainter.isAntiAlias = true
batteryBodyPainter.style = Paint.Style.STROKE
batteryBodyPainter.strokeWidth = OUTLINE_THICKNESS
//电池盖
batteryHeadPainter = Paint()
batteryHeadPainter.color = ColorUtils.getColor(R.color.color_FF0A0A)
batteryHeadPainter.isAntiAlias = true
batteryHeadPainter.style = Paint.Style.FILL
//电量
mPowerPaint = Paint()
mPowerPaint.isAntiAlias = true
mPowerPaint.color = ColorUtils.getColor(R.color.color_3C83FA)
mPowerPaint.style = Paint.Style.FILL
outlineRect = RectF()
outlineRect.left = OUTLINE_THICKNESS
outlineRect.top = OUTLINE_THICKNESS
mCapRect = RectF()
batteryRect = RectF()
}
}
Java版本:
package com.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.blankj.utilcode.util.ColorUtils;
import com.blankj.utilcode.util.ImageUtils;
import com.blankj.utilcode.util.ResourceUtils;
import com.view.R;
/**
* @CreateDate:
* @Author:lp
* @Description:
*/
public class BatteryView extends View {
private static final float OUTLINE_THICKNESS = 3.0f;//电池框厚度
private static final float CAP_WIDTH = 2.0f;//电池盖宽度
private static final float CAP_HEIGHT = 8.0f;//电池盖高度
private static final float GAP_OF_SHAPE_BODY = 2.0f;//电池体与外框之间的间隙
private static final float ROUND_CORNER_RADIUS = 2;
private float fullPowerWidth; //满电量时电池体的宽度。
private int battery = 20;
private Paint batteryBodyPainter;
private Paint batteryHeadPainter;
private Paint mPowerPaint;//电量画笔
private RectF outlineRect;//电池矩形
private RectF mCapRect;//电池盖矩形
private RectF batteryRect;//电量矩形
private int left;
private int top;
public BatteryView(Context context) {
this(context, null);
}
public BatteryView(Context context, AttributeSet attrs) {
super(context, attrs);
//电池外框
batteryBodyPainter = new Paint();
batteryBodyPainter.setColor(ColorUtils.getColor(R.color.color_2CBF6C));
batteryBodyPainter.setAntiAlias(true);
batteryBodyPainter.setStyle(Paint.Style.STROKE);
batteryBodyPainter.setStrokeWidth(OUTLINE_THICKNESS);
//电池盖
batteryHeadPainter = new Paint();
batteryHeadPainter.setColor(ColorUtils.getColor(R.color.color_FF0A0A));
batteryHeadPainter.setAntiAlias(true);
batteryHeadPainter.setStyle(Paint.Style.FILL);
//电量
mPowerPaint = new Paint();
mPowerPaint.setAntiAlias(true);
mPowerPaint.setColor(ColorUtils.getColor(R.color.color_3C83FA));
mPowerPaint.setStyle(Paint.Style.FILL);
outlineRect = new RectF();
outlineRect.left = OUTLINE_THICKNESS;
outlineRect.top = OUTLINE_THICKNESS;
mCapRect = new RectF();
batteryRect = new RectF();
}
public void setBattery(int battery) {
// this.battery = battery > 100 ? 100 : battery < 1 ? 1 : battery;
this.battery = battery;
invalidate();
}
public int getBattery() {
return battery;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int specWidthSize = MeasureSpec.getSize(widthMeasureSpec);//宽
int specHeightSize = MeasureSpec.getSize(heightMeasureSpec);//高
//设置电池外框
outlineRect.right = specWidthSize - OUTLINE_THICKNESS - CAP_WIDTH;
outlineRect.bottom = specHeightSize - OUTLINE_THICKNESS;
//设置电池盖矩形
mCapRect.left = outlineRect.right;
mCapRect.top = (float) specHeightSize / 2 - CAP_HEIGHT / 2;
mCapRect.right = specWidthSize;
mCapRect.bottom = (float) specHeightSize / 2 + CAP_HEIGHT / 2;
//设置电池体
batteryRect.left = outlineRect.left + GAP_OF_SHAPE_BODY;
batteryRect.top = outlineRect.top + GAP_OF_SHAPE_BODY;
batteryRect.bottom = outlineRect.bottom - GAP_OF_SHAPE_BODY;
//闪电位置
left = (int) (specWidthSize / 2 - OUTLINE_THICKNESS * 2);
top = (int) (specHeightSize / 2 - OUTLINE_THICKNESS * 2);
fullPowerWidth = outlineRect.right - GAP_OF_SHAPE_BODY - batteryRect.left;
setMeasuredDimension(specWidthSize, specHeightSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//设置电量矩形
int batter = battery;
if (batter < 0) {
batter = 50;
}
batteryRect.right = (float) batter / 100 * fullPowerWidth + batteryRect.left;
if (battery < 0) {
batteryBodyPainter.setColor(ColorUtils.getColor(R.color.color_818283));
batteryHeadPainter.setColor(ColorUtils.getColor(R.color.color_818283));
mPowerPaint.setColor(ColorUtils.getColor(R.color.color_818283));
} else if (battery <= 20) {
batteryBodyPainter.setColor(ColorUtils.getColor(R.color.color_818283));
batteryHeadPainter.setColor(ColorUtils.getColor(R.color.color_FF4A37));
mPowerPaint.setColor(ColorUtils.getColor(R.color.color_FF4A37));
} else if (battery < 40) {
batteryBodyPainter.setColor(ColorUtils.getColor(R.color.color_41D9B5));
batteryHeadPainter.setColor(ColorUtils.getColor(R.color.color_41D9B5));
mPowerPaint.setColor(ColorUtils.getColor(R.color.color_FF9037));
} else {
batteryBodyPainter.setColor(ColorUtils.getColor(R.color.color_2CBF6C));
batteryHeadPainter.setColor(ColorUtils.getColor(R.color.color_2CBF6C));
mPowerPaint.setColor(ColorUtils.getColor(R.color.color_2CBF6C));
}
canvas.drawRoundRect(outlineRect, ROUND_CORNER_RADIUS, ROUND_CORNER_RADIUS, batteryBodyPainter);
canvas.drawRoundRect(mCapRect, 1, 1, batteryHeadPainter);
canvas.drawRoundRect(batteryRect, ROUND_CORNER_RADIUS, ROUND_CORNER_RADIUS, mPowerPaint);
if (battery >= 0 && battery <= 20) {
Bitmap bitmap = ImageUtils.getBitmap(R.mipmap.shandian);
canvas.drawBitmap(bitmap, left, top, null);
}
}
}
上面代码中使用到的闪电图片(当然也可以去矢量图库下载一个):
使用:在布局文件中:
<com.view.BatteryView
android:id="@+id/batteryVV"
android:layout_width="26dp"
android:layout_height="12dp"
android:layout_marginTop="5dp" />
在代码中直接通过setBattery来设置电量(比如:batteryView.setBattery(50),设置电量为50%),因为项目需求,如果设备离线电池电量灰置(这里直接传入-1表示设备离线),如果低于20就需要增减红色闪电显示(这些都可以根据需要修改源代码),方便简洁,哈哈哈哈哈哈~