android自定义view---电池图标

项目需求,能显示外接设备的电量,要跟外面的妖艳贱货们差不多的效果。

简单不是么,我能直接找as生成这么多好看的图标,你怕不怕?

《android自定义view---电池图标》

——不行,我要是电量21怎么办?

。。。天杀的处女座啊。

需求要和md的图标一样的风格,于是先下一个研究一下它的配色和构成

《android自定义view---电池图标》 xml配置

这里可以得到一个点,就是背景颜色alpha是.3,也就是77左右,

《android自定义view---电池图标》 电池

再看电池的形状,其实仔细剖析还是比较简单的:

上面一个矩形,下面一个圆角矩形

OK,思路就出来了:

  1. 首先定义哪些需要暴露的属性:前景色,电量百分比(int,同时设置set入口)
  2. 先用alpha为77的黑色画一个背景电池的形状;
  3. 根据传入的电量百分比裁剪画布;
  4. 换好前景色, 再把电池画一遍。
    当然有不可避免的重绘,这里先不管了,当然有强迫症的话可以裁剪两次。。。

先是attrs声明好需要外部设置的属性:

<declare-styleable name="BattaryView">
        <attr name="battaryPercnet" format="integer"/>
        <attr name="color"/>
    </declare-styleable>

实现View的子类,获取属性,重写onMeasure()和onDraw():

先是成员变量,这次很简单

    private int battaryPercent;//电量百分比
    private int color;//前景色
    private float round;//圆角大小,这里写死,省去使用时计算

构造方法拿到属性

public BattaryView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.BattaryView, 0, defStyleAttr);

        for (int i = 0; i < typedArray.length(); i++) {
            int attr = typedArray.getIndex(i);
            switch (attr) {
                case R.styleable.BattaryView_battaryPercnet:
                    battaryPercent = typedArray.getInteger(attr, 0);
                    break;
                case R.styleable.BattaryView_color:
                    color = typedArray.getColor(attr, Color.BLACK);
                    break;
            }
        }
        typedArray.recycle();
        mPaint = new Paint();
        mPaint.setColor(color);
        mPaint.setAntiAlias(true);
    }

onMeasure()简单的写一下,这次就先省略了,xml里面写死(其实是发现麻烦懒得写了)

onDraw() 代码里面注解挺详细的

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        round = getHeight() / 40f;//把圆角写死,省去使用时计算
        mPaint.setStyle(Paint.Style.FILL);//填充模式
        //电池区域的高,宽
        int imgH = getHeight() - getPaddingTop() - getPaddingBottom();
        int imgW = (getWidth() < getHeight() / 2) ? (getWidth() - getPaddingLeft() - getPaddingRight()) : getHeight() / 2;
        //根据电量百分比得到的矩形,top和bottom先占位,等一下再重新赋值,也可以new RectF()里面空参,四个属性挨个设置
        RectF rectF = new RectF(
                (float) getPaddingLeft(),
                0,
                (float) getPaddingLeft() + imgW,
                0);
        float spaceTop = (getHeight() - imgH) / 2 + getPaddingTop();
        rectF.top = spaceTop + (1.0f - battaryPercent * 1.0f / 100) * imgH;
        rectF.bottom = getHeight() - spaceTop;
        //上面这三行其实有电多余,由于刚开始是想设置at most时的状况的,后来发现太麻烦,急着用就先这样了。
        
        int layerId = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);
        int h1 = imgH / 8;//电池凸点的高度
        int w1 = imgW / 3;//电池凸点的宽度
        //绘制背景
        mPaint.setColor(Color.argb(77, 0, 0, 0));
        canvas.drawRoundRect(rectF.left,h1 + getPaddingTop(),rectF.right,getHeight() - getPaddingBottom(),round,round,mPaint);
        canvas.drawRect(getPaddingLeft() + w1,getPaddingTop(),rectF.right - w1,h1 + getPaddingTop(),mPaint);
        //绘制有电部分
        canvas.save();
        canvas.clipRect(rectF);
        mPaint.setColor(color);
        canvas.drawRoundRect(rectF.left, getPaddingTop() + h1, rectF.right, rectF.bottom, round, round, mPaint);
        canvas.drawRect(rectF.left + w1, rectF.top, rectF.right - w1, getPaddingTop() + h1 + h1 / 10, mPaint);
        canvas.restore();
        canvas.restoreToCount(layerId);
    }

好了,然后简单调用测试:

《android自定义view---电池图标》

差不多,再加上set方法,试试动态设置电量看看
自定义view类里面:

    public void setBattaryPercent(int battaryPercent) {
        this.battaryPercent = battaryPercent;
        postInvalidate();
    }

activity中与seekbar结合使用,比较简单了。直接放效果:

《android自定义view---电池图标》
《android自定义view---电池图标》
《android自定义view---电池图标》

看小图其实圆角有点小了,可以自己改一下比例。。。

源码点击查看

    原文作者:Vonelone
    原文地址: https://www.jianshu.com/p/4867493f74fb
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞