自定义view - 进度条

1,437 阅读3分钟

废话不多说先看效果图

效果图
效果图

原谅模拟器显示的不好看,为了录GIF图,只能用模拟器

思路分析

一个背景,一个进度,一个进度值显示,进度条与文字显示的高度是1:2,其中用到了drawRoundRect用来画带圆角的矩形,空心与实心都是Paint的属性设置的,drawText用来画文字

注意点:

1.进度条进度满进度与未满进度,计算onewidth = mwidth / mMaxProgress(单位进度占的宽度=总宽度/满进度);
2.文字显示,先计算文字的宽度,三个状态(起始位置 <= 文字宽度 / 当前位置 +文字宽度>=宽度/之间的),分别进行计算

实现

onDraw来画图了

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        float x = onewidth * mCurrentProgress;
        //画背景
        RectF rectF = new RectF(0, 0, mwidth, bheight);
        canvas.drawRoundRect(rectF, num8, num8, backgroudPaint);
        //画进度条
        RectF rectFm;
        if (mCurrentProgress == mMaxProgress) {
            rectFm = new RectF(num2, num2, mwidth - num2, bheight - num2);
        } else {
            rectFm = new RectF(num2, num2, x + num2, bheight - num2);
        }
        canvas.drawRoundRect(rectFm, num8, num8, mPaint);
        //画文字
        //获取文字的宽度及其高度
        Rect rect = new Rect();
        String speed = mCurrentProgress + "%";
        txtPaint.getTextBounds(speed, 0, speed.length(), rect);
        textheight = rect.height();
        textwidth = rect.width();
        if (mCurrentProgress == mMaxProgress) {
            canvas.drawText(speed, mwidth - textwidth, txtheight, txtPaint);
        } else {

            //起始位置 <= 文字宽度
            if (x <= textwidth) {
                canvas.drawText(speed, textwidth / 2, txtheight, txtPaint);
                //当前位置 +文字宽度>=宽度
            } else if (x + textwidth >= mwidth) {
                canvas.drawText(speed, mwidth - textwidth - 2 * num8, txtheight, txtPaint);
            } else {
                canvas.drawText(speed, x - textwidth / 2, txtheight, txtPaint);
            }
        }

    }

设置进度

    public void setProgress(int progress) {
        if (progress <= 100 && progress >= 0) {
            this.mCurrentProgress = progress;
            invalidate();
        }
    }

实际项目中,可有很多的扩展,但是有时候实际项目不需要把很多不需要的方法,设置属性的方法等给写出来,根据项目的需求去写相关方法、属性设置

完整代码

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.numberview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by wujun on 2017/9/20.
 *
 * @author madreain
 * @desc
 */

public class NumberView1 extends View {

    Paint backgroudPaint;
    Paint mPaint;
    Paint txtPaint;

    //宽高
    int mwidth, mheight;
    int bheight, txtheight;

    private int mMaxProgress = 100;
    private int mCurrentProgress = 0;
    private float onewidth;

    //文字显示的宽高
    int textheight;
    int textwidth;

    float num8;
    float num2;

    //    30 10  20

    public NumberView1(Context context) {
        super(context);
        init();
    }

    public NumberView1(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public NumberView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        backgroudPaint = new Paint();
        backgroudPaint.setAntiAlias(true);
        backgroudPaint.setStyle(Paint.Style.STROKE);
        backgroudPaint.setStrokeCap(Paint.Cap.ROUND);
        backgroudPaint.setColor(Color.rgb(51, 197, 167));

        txtPaint = new Paint();
        txtPaint.setAntiAlias(true);
        txtPaint.setStyle(Paint.Style.FILL);
        txtPaint.setColor(Color.rgb(51, 197, 167));
        txtPaint.setTextSize(sp2px(12));
        txtPaint.setStrokeWidth(2);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setColor(Color.rgb(51, 197, 167));

        num8 = dp2px(8);
        num2 = dp2px(2);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mwidth = w;
        mheight = h;
        bheight = mheight / 3;
        txtheight = bheight * 2;
        onewidth = mwidth / mMaxProgress;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        float x = onewidth * mCurrentProgress;
        //画背景
        RectF rectF = new RectF(0, 0, mwidth, bheight);
        canvas.drawRoundRect(rectF, num8, num8, backgroudPaint);
        //画进度条
        RectF rectFm;
        if (mCurrentProgress == mMaxProgress) {
            rectFm = new RectF(num2, num2, mwidth - num2, bheight - num2);
        } else {
            rectFm = new RectF(num2, num2, x + num2, bheight - num2);
        }
        canvas.drawRoundRect(rectFm, num8, num8, mPaint);
        //画文字
        //获取文字的宽度及其高度
        Rect rect = new Rect();
        String speed = mCurrentProgress + "%";
        txtPaint.getTextBounds(speed, 0, speed.length(), rect);
        textheight = rect.height();
        textwidth = rect.width();
        if (mCurrentProgress == mMaxProgress) {
            canvas.drawText(speed, mwidth - textwidth, txtheight, txtPaint);
        } else {

            //起始位置 <= 文字宽度
            if (x <= textwidth) {
                canvas.drawText(speed, textwidth / 2, txtheight, txtPaint);
                //当前位置 +文字宽度>=宽度
            } else if (x + textwidth >= mwidth) {
                canvas.drawText(speed, mwidth - textwidth - 2 * num8, txtheight, txtPaint);
            } else {
                canvas.drawText(speed, x - textwidth / 2, txtheight, txtPaint);
            }
        }

    }

    public float dp2px(float dp) {
        final float scale = getResources().getDisplayMetrics().density;
        return dp * scale + 0.5f;
    }

    public float sp2px(float sp) {
        final float scale = getResources().getDisplayMetrics().scaledDensity;
        return sp * scale;
    }

    public void setProgress(int progress) {
        if (progress <= 100 && progress >= 0) {
            this.mCurrentProgress = progress;
            invalidate();
        }
    }

}

自定义view多写多练

NumberView github demo地址