如何在android中创建电池电量指示器?

如何在android中创建电池电量指示器?,android,android-layout,user-interface,batterylevel,Android,Android Layout,User Interface,Batterylevel,我想创建一个电池电量指示器,如图所示(我在图中圈出)。绿色部分应根据设备中的可用电池填充 像这样从设备获取电池百分比 registerReceiver(mBatInfoReceiver, new IntentFilter( Intent.ACTION_BATTERY_CHANGED)); 因此,在布局中,我能够显示电池百分比 public class BatteryIndicatorActivity extends Activity { //Create

我想创建一个电池电量指示器,如图所示(我在图中圈出)。绿色部分应根据设备中的可用电池填充

像这样从设备获取电池百分比

registerReceiver(mBatInfoReceiver, new IntentFilter(
            Intent.ACTION_BATTERY_CHANGED));
因此,在布局中,我能够显示电池百分比

public class BatteryIndicatorActivity extends Activity {
        //Create Broadcast Receiver Object along with class definition
    private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {
        @Override
          //When Event is published, onReceive method is called
        public void onReceive(Context c, Intent i) {
              //Get Battery %
            int level = i.getIntExtra("level", 0);
            TextView tv = (TextView) findViewById(R.id.textfield);
              //Set TextView with text
            tv.setText("Battery Level: " + Integer.toString(level) + "%");
        }

    };
但是如何为这种类型的电池指示器创建UI。他们是否有api来实现这一点?如果没有,如何创建这种类型的UI


我们将感谢您的帮助。

有很多方法可以做到这一点。以下是其中的几个:

  • 使用
    进度条
    ,使其垂直,使其以电池形状绘制
  • 使用自定义的
    视图
    ,在其中覆盖
    onDraw()
    ,并在
    画布上绘制电池形状
  • 使用带有透明电池形状的白色图像。将其放置在视图上,在该视图中垂直填充背景,或更改背景视图的高度

  • 有很多方法可以做到这一点。以下是其中的几个:

  • 使用
    进度条
    ,使其垂直,使其以电池形状绘制
  • 使用自定义的
    视图
    ,在其中覆盖
    onDraw()
    ,并在
    画布上绘制电池形状
  • 使用带有透明电池形状的白色图像。将其放置在视图上,在该视图中垂直填充背景,或更改背景视图的高度

  • 这是显示电池电量的自定义视图

    class BatteryView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
        View(context, attrs, defStyleAttr) {
        private var radius: Float = 0f
        private var isCharging: Boolean = false
    
        // Top
        private var topPaint =
            PaintDrawable(Color.WHITE) // I only want to corner top-left and top-right so I use PaintDrawable instead of Paint
        private var topRect = Rect()
        private var topPaintWidthPercent = 50
        private var topPaintHeightPercent = 8
    
        // Border
        private var borderPaint = Paint().apply {
            color = Color.BLUE
            style = Paint.Style.STROKE
        }
        private var borderRect = RectF()
        private var borderStrokeWidthPercent = 8
        private var borderStroke: Float = 0f
    
        // Percent
        private var percentPaint = Paint()
        private var percentRect = RectF()
        private var percentRectTopMin = 0f
        private var percent: Int = 0
    
        // Charging
        private var chargingRect = RectF()
        private var chargingBitmap: Bitmap? = null
    
        init {
            init(attrs)
            chargingBitmap = getBitmap(R.drawable.ic_charging)
        }
    
        private fun init(attrs: AttributeSet?) {
            val ta = context.obtainStyledAttributes(attrs, R.styleable.BatteryView)
            try {
                percent = ta.getInt(R.styleable.BatteryView_bv_percent, 0)
                isCharging = ta.getBoolean(R.styleable.BatteryView_bv_charging, false)
            } finally {
                ta.recycle()
            }
        }
    
        @SuppressLint("DrawAllocation")
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            val measureWidth = View.getDefaultSize(suggestedMinimumWidth, widthMeasureSpec)
            val measureHeight = (measureWidth * 1.8f).toInt()
            setMeasuredDimension(measureWidth, measureHeight)
    
            radius = borderStroke / 2
            borderStroke = (borderStrokeWidthPercent * measureWidth).toFloat() / 100
    
            // Top
            val topLeft = measureWidth * ((100 - topPaintWidthPercent) / 2) / 100
            val topRight = measureWidth - topLeft
            val topBottom = topPaintHeightPercent * measureHeight / 100
            topRect = Rect(topLeft, 0, topRight, topBottom)
    
            // Border
            val borderLeft = borderStroke / 2
            val borderTop = topBottom.toFloat() + borderStroke / 2
            val borderRight = measureWidth - borderStroke / 2
            val borderBottom = measureHeight - borderStroke / 2
            borderRect = RectF(borderLeft, borderTop, borderRight, borderBottom)
    
            // Progress
            val progressLeft = borderStroke
            percentRectTopMin = topBottom + borderStroke
            val progressRight = measureWidth - borderStroke
            val progressBottom = measureHeight - borderStroke
            percentRect = RectF(progressLeft, percentRectTopMin, progressRight, progressBottom)
    
            // Charging Image
            val chargingLeft = borderStroke
            var chargingTop = topBottom + borderStroke
            val chargingRight = measureWidth - borderStroke
            var chargingBottom = measureHeight - borderStroke
            val diff = ((chargingBottom - chargingTop) - (chargingRight - chargingLeft))
            chargingTop += diff / 2
            chargingBottom -= diff / 2
            chargingRect = RectF(chargingLeft, chargingTop, chargingRight, chargingBottom)
        }
    
        override fun onDraw(canvas: Canvas) {
            drawTop(canvas)
            drawBody(canvas)
            if (!isCharging) {
                drawProgress(canvas, percent)
            } else {
                drawCharging(canvas)
            }
        }
    
        private fun drawTop(canvas: Canvas) {
            topPaint.bounds = topRect
            topPaint.setCornerRadii(floatArrayOf(radius, radius, radius, radius, 0f, 0f, 0f, 0f))
            topPaint.draw(canvas)
        }
    
        private fun drawBody(canvas: Canvas) {
            borderPaint.strokeWidth = borderStroke
            canvas.drawRoundRect(borderRect, radius, radius, borderPaint)
        }
    
        private fun drawProgress(canvas: Canvas, percent: Int) {
            percentPaint.color = getPercentColor(percent)
            percentRect.top = percentRectTopMin + (percentRect.bottom - percentRectTopMin) * (100 - percent) / 100
            canvas.drawRect(percentRect, percentPaint)
        }
    
        // todo change color
        private fun getPercentColor(percent: Int): Int {
            if (percent > 50) {
                return Color.WHITE
            }
            if (percent > 30) {
                return Color.YELLOW
            }
            return Color.RED
        }
    
        private fun drawCharging(canvas: Canvas) {
            chargingBitmap?.let {
                canvas.drawBitmap(it, null, chargingRect, null)
            }
        }
    
        private fun getBitmap(drawableId: Int, desireWidth: Int? = null, desireHeight: Int? = null): Bitmap? {
            val drawable = AppCompatResources.getDrawable(context, drawableId) ?: return null
            val bitmap = Bitmap.createBitmap(
                desireWidth ?: drawable.intrinsicWidth,
                desireHeight ?: drawable.intrinsicHeight,
                Bitmap.Config.ARGB_8888
            )
            val canvas = Canvas(bitmap)
            drawable.setBounds(0, 0, canvas.width, canvas.height)
            drawable.draw(canvas)
            return bitmap
        }
    
        fun charge() {
            isCharging = true
            invalidate() // can improve by invalidate(Rect)
        }
    
        fun unCharge() {
            isCharging = false
            invalidate()
        }
    
        fun setPercent(percent: Int) {
            if (percent > 100 || percent < 0) {
                return
            }
            this.percent = percent
            invalidate()
        }
    
        fun getPercent(): Int {
            return percent
        }
    }
    
    class BatteryView@JVM重载构造函数(上下文:context,attrs:AttributeSet?=null,defStyleAttr:Int=0):
    视图(上下文、属性、defStyleAttr){
    专用变量半径:浮点=0f
    专用var放电:布尔值=false
    //顶
    私人油漆=
    PaintDrawable(Color.WHITE)//我只想左上角和右上角,所以我使用PaintDrawable而不是Paint
    私有变量topRect=Rect()
    私有风险值百分比=50
    私有变量topPaintHeightPercent=8
    //边界
    私有变量borderPaint=Paint()。应用{
    颜色=color.BLUE
    style=Paint.style.STROKE
    }
    私有变量borderRect=RectF()
    私有变量borderStrokeWidthPercent=8
    私有变量borderStroke:Float=0f
    //百分比
    私有变量percentPaint=Paint()
    私有变量percentRect=RectF()
    私有变量percentRectTopMin=0f
    私有变量百分比:Int=0
    //充电
    私有变量chargingRect=RectF()
    私有变量chargingBitmap:位图?=null
    初始化{
    初始化(属性)
    chargingBitmap=getBitmap(R.drawable.ic_充电)
    }
    私人娱乐初始(属性集?){
    val ta=context.actainstyledattributes(attrs,R.styleable.battyview)
    试一试{
    percent=ta.getInt(R.styleable.BatteryView\u bv\u percent,0)
    放电=ta.getBoolean(R.styleable.BatteryView\u bv\u充电,false)
    }最后{
    ta.回收()
    }
    }
    @SuppressLint(“DrawAllocation”)
    覆盖测量时的乐趣(widthMeasureSpec:Int,heightMeasureSpec:Int){
    val measureWidth=View.getDefaultSize(建议的最小宽度、宽度度量等级)
    val measurewhight=(measureWidth*1.8f).toInt()
    设置测量尺寸(测量宽度、测量高度)
    半径=边界笔划/2
    borderStroke=(borderStrokeWidthPercent*measureWidth).toFloat()/100
    //顶
    val topLeft=测量宽度*((100-topPaintWidthPercent)/2)/100
    val topRight=测量宽度-topLeft
    val topBottom=顶部高度百分比*测量高度/100
    topRect=Rect(上左、0、上右、上下)
    //边界
    val borderLeft=borderStroke/2
    val borderTop=topBottom.toFloat()+borderStroke/2
    val borderRight=测量宽度-边界笔划/2
    val borderBottom=测量高度-borderStroke/2
    borderRect=RectF(borderLeft、borderTop、borderRight、borderBottom)
    //进展
    val progressLeft=边界笔划
    percentRectTopMin=上下+边界笔划
    val progressRight=测量宽度-边界行程
    val progressBottom=测量高度-边界行程
    percentRect=RectF(progressLeft、percentRectTopMin、progressRight、progressBottom)
    //充电图像
    val chargingLeft=边界笔划
    var chargingTop=上下+边界笔划
    val chargingRight=测量宽度-边界行程
    var chargingBottom=测量高度-边界冲程
    val diff=((chargingBottom-chargingTop)-(chargingRight-chargingLeft))
    chargingTop+=diff/2
    chargingBottom-=diff/2
    chargingRect=RectF(chargingLeft、chargingTop、chargingRight、chargingBottom)
    }
    覆盖onDraw(画布:画布){
    拉手(帆布)
    抽体(帆布)
    如果(!放电){
    绘图进度(画布,百分比)
    }否则{
    抽纱(帆布)
    }
    }
    私人趣味吸顶(帆布:帆布){
    topaint.bounds=topRect
    topPaint.setCornerRadii(浮动阵列OF(半径、半径、半径、半径、0f、0f、0f、0f))
    顶部绘制(画布)
    }
    私人趣味抽体(帆布:帆布){
    borderPaint.strokeWidth=borderStroke
    canvas.drawRoundRect(borderRect,radius,radius,borderPaint)
    }
    私人趣味drawProgress(画布:画布,百分比:整数){
    percentPaint.color=getPercentColor(百分比)
    percentRect.top=percentRectTopMin+(percentRect.bottom-percentRectTopMin)*(100%)/100
    canvas.drawRect(percentRect,percentPaint)
    }
    //todo变色
    私人娱乐getPercentColor(百分比:Int):Int{
    如果(百分比>50){
    返回颜色。白色
    }
    如果(百分比>30){
    返回颜色。黄色
    }
    返回颜色:红色
    }
    私人娱乐抽奖收费(画布:画布){
    Charging?让我来{
    可以
    
    <declare-styleable name="BatteryView">
        <attr name="bv_charging" format="boolean" />
        <attr name="bv_percent" format="integer" />
    </declare-styleable>
    
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="368.492"
        android:viewportHeight="368.492">
        <path
            android:fillColor="#FFFFFF"
            android:pathData="M297.51,150.349c-1.411,-2.146 -3.987,-3.197 -6.497,-2.633l-73.288,16.498L240.039,7.012c0.39,-2.792 -1.159,-5.498 -3.766,-6.554c-2.611,-1.069 -5.62,-0.216 -7.283,2.054L71.166,217.723c-1.489,2.035 -1.588,4.773 -0.246,6.911c1.339,2.132 3.825,3.237 6.332,2.774l79.594,-14.813l-23.257,148.799c-0.436,2.798 1.096,5.536 3.714,6.629c0.769,0.312 1.562,0.469 2.357,0.469c1.918,0 3.78,-0.901 4.966,-2.517l152.692,-208.621C298.843,155.279 298.916,152.496 297.51,150.349z" />
    </vector>
    
    <package.BatteryView
            android:id="@+id/battery_view"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_charging"
            app:bv_charging="false"
            app:bv_percent="20" />