Android仿苹果电量显示

自定义View

自定义电池电量的 View如下:

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View

class BatteryView : View {
    private var mMaxLevel = 100
    private var mLinePaint: Paint? = null
    private var mBatteryPaint: Paint? = null
    private var mRectPaint: Paint? = null
    private var mTextPaint: Paint? = null
    private var mRectF: RectF? = null
    private var mWidth = 0
    private var mHeight = 0
    private var mPerPartWidth = 0
    private var mBatteryLevel = 0
    private var mHeaderHeight = 0 //电池头部高度

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mWidth = MeasureSpec.getSize(widthMeasureSpec)
        mHeight = MeasureSpec.getSize(heightMeasureSpec)
        if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.UNSPECIFIED
            || MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST
        ) {
            mWidth = 150
        }
        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED
            || MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST
        ) {
            mHeight = 80
        }
        mPerPartWidth = (mWidth - BATTERY_HEADER_WIDTH) / PART_COUNT
        mHeaderHeight = mHeight / 3
        setMeasuredDimension(mWidth, mHeight)
    }

    private fun init() {
        mLinePaint = Paint()
        mLinePaint!!.isAntiAlias = true
        mLinePaint!!.color = Color.WHITE
        mBatteryPaint = Paint()
        mBatteryPaint!!.isAntiAlias = true
        mBatteryPaint!!.color = Color.WHITE
        mRectPaint = Paint()
        mRectPaint!!.isAntiAlias = true
        mRectPaint!!.color = Color.GRAY
        mRectPaint!!.style = Paint.Style.FILL
        mTextPaint = Paint()
        mTextPaint!!.color = Color.BLACK
        mTextPaint!!.textSize = 50f
        mTextPaint!!.style = Paint.Style.FILL
        mTextPaint!!.textAlign = Paint.Align.CENTER
        mRectF = RectF()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val batteryWidth = mWidth - BATTERY_HEADER_WIDTH

        //绘制电池背景
        mRectF!!.right = batteryWidth.toFloat()
        mRectF!!.bottom = mHeight.toFloat()
        canvas.drawRoundRect(mRectF!!, 20f, 20f, mRectPaint!!)

        //绘制当前电量
        canvas.save()
        canvas.clipRect(0, 0, batteryWidth * mBatteryLevel / mMaxLevel, mHeight) //裁剪矩形
        canvas.drawRoundRect(mRectF!!, 20f, 20f, mBatteryPaint!!)
        canvas.restore()
        if (DRAW_PART_LINE) {
            //绘制电池分格线
            for (i in 1 until PART_COUNT) {
                canvas.drawLine(
                    (mPerPartWidth * i).toFloat(),
                    0f,
                    (mPerPartWidth * i).toFloat(),
                    mHeight.toFloat(),
                    mLinePaint!!
                )
            }
        }

        //绘制电量文字
        val fontMetrics = mTextPaint!!.fontMetrics
        val top = fontMetrics.top //基线到字体上边框的距离
        val bottom = fontMetrics.bottom //基线到字体下边框的距离
        val baseLineY = (mRectF!!.centerY() - top / 2 - bottom / 2).toInt() //基线中间点的y轴
        canvas.drawText(
            mBatteryLevel.toString(),
            mRectF!!.centerX(),
            baseLineY.toFloat(),
            mTextPaint!!
        )

        //绘制右边电池头部
        mRectF!!.left = batteryWidth.toFloat()
        mRectF!!.top = (mHeight / 2 - mHeaderHeight / 2).toFloat()
        mRectF!!.right = (mRectF!!.left + BATTERY_HEADER_WIDTH).toFloat()
        mRectF!!.bottom = (mHeight / 2 + mHeaderHeight / 2).toFloat()
        mRectPaint!!.style = Paint.Style.FILL
        canvas.drawRect(mRectF!!, mRectPaint!!)
    }

    fun setBatteryLevel(level: Int) {
        mBatteryLevel = level
        if (level <= 10) {
            mBatteryPaint!!.color = Color.RED
        } else {
            mBatteryPaint!!.color = Color.WHITE
        }
        postInvalidate()
    }

    fun setMaxLevel(maxLevel: Int) {
        mMaxLevel = maxLevel
        postInvalidate()
    }

    companion object {
        private const val DRAW_PART_LINE = false //是否绘制分格线
        private const val PART_COUNT = 4 //分格总数
        private const val BATTERY_HEADER_WIDTH = 8 //右边电池头宽度
    }
}

自定义中通过 Canvas.clipRect()函数裁剪圆角矩形,实现类似苹果电量的半圆角半直角的效果。

电量监听

主界面代码监听电量变化的广播:

class MainActivity : AppCompatActivity() {
    private var mBatteryView: BatteryView? = null
    protected fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_fullscreen)
        mBatteryView = findViewById(R.id.battery_view)

        val filter = IntentFilter()
        filter.addAction(Intent.ACTION_BATTERY_CHANGED)
        registerReceiver(receiver, filter)
    }

    private val receiver: BroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action!! == Intent.ACTION_BATTERY_CHANGED) {
                //当前电量
                val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
                //最大电池电量
                val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)
                //电池状态
                val status: Int = intent.getIntExtra(BatteryManager.EXTRA_STATUS, 100)
                mBatteryView!!.setBatteryLevel(level)
            }
            }
        }
    }

    protected fun onDestroy() {
        unregisterReceiver(receiver)
        super.onDestroy()
    }
}

其中 BatteryManager.EXTRA_LEVEL为当前电量;BatteryManager.EXTRA_SCALE为电池容量即最大电量(基本都为100);BatteryManager.EXTRA_STATUS为电池状态,以此判断是否在充电状态。

效果

电量100%时显示如下:
Android仿苹果电量显示_第1张图片
小于等于10%为低电量,显示预警色(可根据需要调节低电量阈值):
Android仿苹果电量显示_第2张图片
电量20%:
Android仿苹果电量显示_第3张图片
可通过 DRAW_PART_LINE 的布尔常量设置是否要分格并显示分格线:
Android仿苹果电量显示_第4张图片
上述内容默认最大电量为100,可通过 setMaxLevel()方法设置最大电池容量。

你可能感兴趣的:(自定义View,Kotlin,android,电量UI,电池电量,自定义View,Kotlin)