欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自定义View之线性百分比进度条

程序员文章站 2024-02-05 20:43:46
...

先上效果图再分析:
自定义View之线性百分比进度条
从图中可以看到本view支持两种不同的类型进度展示,一种是进度百分比直接用textview展示,另一种加了矩形背景。第一种没什么难度,本文就以第二种为例讲解一下,一步一步实现,你会发现原来很简单。

  // 线的X起始左标
   // private float startX;
  //  private float endX;
//private float pading = 100f; // 左右边距
 @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
        startX = paintWidth+pading;
        endX = width -pading;
    }
   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 根据 progress进度 ,获得X坐标
         lenth = (endX*progress/100)+startX-(progress/100*(startX));
        // 底部背景线
       canvas.drawLine(startX,height/2,endX,height/2,paint);
        // 画 进度线
       drawLine(canvas);
        if (type==1){
            // 不带矩形的进度
            drawText(canvas);
        }else if (type==2){
            // 画带三角形的矩形进度条
            drawRecText(canvas);

        }
    }

首先在onSizeChanged方法中测量view宽高和线的起始位置,在onDraw方法中进行类型判断和根据 progress进度 获得X坐标,然后开始画图。

第一步画背景线

// 底部背景线
canvas.drawLine(startX,height/2,endX,height/2,paint);

效果如下:
自定义View之线性百分比进度条

第二步 画进度线并实现动画效果

先画线

 canvas.drawLine(startX,height/2,lenth,height/2,mPaint);

动画效果

// 设置进度
    public void setProgress(int mprogress) {
        ValueAnimator anim = ValueAnimator.ofFloat(0, mprogress);
        anim.setDuration(3000);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                progress = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        anim.start();
    }

根据ValueAnimator 获取progress值,连续调用invalidate()进行重绘。
自定义View之线性百分比进度条

第三步实现画矩形和内部文字

 String text =(int) progress+"%";

        ttPaint.getTextBounds(text, 0, text.length(), tTextRect);
        float TextHeight = tTextRect.height();
        float TextWidth = tTextRect.width();

        tRect.set((int)(lenth-TextWidth/2-4f),(int)(height/2-2*TextHeight-6f),(int)(lenth+TextWidth/2+4f),(int)(height/2-TextHeight));
        // 画矩形
        canvas.drawRect(tRect,recPaint);

        Paint.FontMetricsInt fontMetrics = ttPaint.getFontMetricsInt();
        // 获取baseLine
        int baseline = tRect.top + (tRect.bottom - tRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
        ttPaint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText(text,tRect.centerX(),baseline, ttPaint);

首先获取文本内容宽高,然后根据文本的宽高设置矩形的初始位置,并画出,为了不让文字紧贴矩形这里适当调整一下矩形宽高,然后在矩形的中心画出文本内容 。
自定义View之线性百分比进度条

第四步 画三角形

// 画三角形
        path.moveTo(lenth, (float) (height/2-0.7*TextHeight));
        path.lineTo((float) (lenth-0.15*TextWidth),  height / 2-TextHeight);
        path.lineTo((float) (lenth+0.15*TextWidth), height / 2-TextHeight);
        canvas.drawPath(path, recPaint);
        path.reset();

注意: 如果你问我上边方法的百分比为什么是0.15和0.7的话我会明确的告诉你我不知道!!!三角型的大小需要根据矩形的大小和位置来调整,只到你认为合适为止,所以你可以随意更改三角形的起始y坐标,连接的X坐标也可以随便更改,所以这里的百分比只是我自己调试看着顺眼。。。
自定义View之线性百分比进度条

全部代码

/**
 * Created by Administrator on 2017/8/24 0024.
 */

public class MyLinearProgressView extends View{
    private Context mcontext ;
    private Paint  paint ; // 初始画线笔
    private Paint mPaint; // 进度画线笔

    private Paint recPaint;// 矩形画笔

    private float paintWidth ; // 画笔宽度
    private  int    paintColor; // 画笔颜色
    private  float textSize ; // 百分比text的大小
    private Paint tPaint; // 不带矩形的Text画笔
    private Paint ttPaint; // 带矩形的Text画笔

    // 当前进度
    private  float progress = 1;
    /*
   * view的高度
   */
    private int height;
    private int width;
    /* 测量文本宽高的矩形 */
    private Rect tTextRect;

    /* 文本的矩形 */
    private Rect tRect;

        private float pading = 100f; // 左右边距
    // 线的X起始左标
    private float startX;
    private float endX;

    private  int type ; // 那种风格
    /**
     * 画三角形的path
     */
    private Path path = new Path();
    private float lenth;

    public MyLinearProgressView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mcontext = context;
        getAtt(attrs);
        initPaint();
    }

    private void getAtt(AttributeSet attrs) {
        TypedArray typedArray = mcontext.obtainStyledAttributes(attrs, R.styleable.MyLinearProgressView);
        paintColor = typedArray.getColor(R.styleable.MyLinearProgressView_lp_paintColor,  Color.parseColor("#df0781"));
        paintWidth = typedArray.getDimension(R.styleable.MyLinearProgressView_lp_paintWidth,dp2px(10));
        textSize = typedArray.getDimension(R.styleable.MyLinearProgressView_lp_textSize,30f);
        type = typedArray.getInt(R.styleable.MyLinearProgressView_lp_type,1);
        typedArray.recycle();
        tTextRect = new Rect();
        tRect  = new Rect();
    }
    private void initPaint() {
        paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor( Color.parseColor("#e1e1e1"));
        paint.setStrokeWidth(paintWidth);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true);

        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.RED);
        mPaint.setStrokeWidth(paintWidth);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setAntiAlias(true);

        tPaint = new Paint();
        tPaint.setStyle(Paint.Style.FILL);
        tPaint.setColor(Color.RED);
        tPaint.setStrokeWidth(paintWidth);
        tPaint.setTextSize(textSize);
        tPaint.setAntiAlias(true);

        ttPaint = new Paint();
        ttPaint.setStyle(Paint.Style.FILL);
        ttPaint.setColor(Color.WHITE);
        ttPaint.setStrokeWidth(paintWidth);
        ttPaint.setTextSize(textSize);
        ttPaint.setAntiAlias(true);

        recPaint = new Paint();
        recPaint.setStyle(Paint.Style.FILL);
        recPaint.setColor(Color.RED);
        recPaint.setAntiAlias(true);
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
        startX = paintWidth+pading;
        endX = width -pading;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 根据 progress进度 ,获得X坐标
         lenth = (endX*progress/100)+startX-(progress/100*(startX));
        // 底部背景线
       canvas.drawLine(startX,height/2,endX,height/2,paint);
        // 画 进度线
       drawLine(canvas);
        if (type==1){
            // 不带矩形的进度
            drawText(canvas);
        }else if (type==2){
            // 画带三角形的矩形进度条
           drawRecText(canvas);

        }
    }


    private void drawRecText(Canvas canvas) {
        String text =(int) progress+"%";
        ttPaint.getTextBounds(text, 0, text.length(), tTextRect);
        float TextHeight = tTextRect.height();
        float TextWidth = tTextRect.width();

        tRect.set((int)(lenth-TextWidth/2-4f),(int)(height/2-2*TextHeight-6f),(int)(lenth+TextWidth/2+4f),(int)(height/2-TextHeight));
        // 画矩形
        canvas.drawRect(tRect,recPaint);

        Paint.FontMetricsInt fontMetrics = ttPaint.getFontMetricsInt();
        // 获取baseLine
        int baseline = tRect.top + (tRect.bottom - tRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
        ttPaint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText(text,tRect.centerX(),baseline, ttPaint);

        // 画三角形
        path.moveTo(lenth, (float) (height/2-0.7*TextHeight));
        path.lineTo((float) (lenth-0.15*TextWidth),  height / 2-TextHeight);
        path.lineTo((float) (lenth+0.15*TextWidth), height / 2-TextHeight);
        canvas.drawPath(path, recPaint);
        path.reset();

    }


    private void drawText(Canvas canvas) {

        String text =(int) progress+"%";
        tPaint.getTextBounds(text, 0, text.length(), tTextRect);
        float TextHeight = tTextRect.height();
        canvas.drawText(text,lenth+6f,height/2+TextHeight/2, tPaint);

    }

    private void drawLine(Canvas canvas) {

        canvas.drawLine(startX,height/2,lenth,height/2,mPaint);
    }
   // 设置进度
    public void setProgress(int mprogress) {
        ValueAnimator anim = ValueAnimator.ofFloat(0, mprogress);
        anim.setDuration(3000);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                progress = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        anim.start();
    }
  //  设置类型
    public void  setType(int mtype){
        type = mtype;
        invalidate();
    }

    /**
     * dp 2 px
     *
     * @param dpVal
     */
    protected int dp2px(int dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getResources().getDisplayMetrics());
    }
}

attr 文件

<declare-styleable name="MyLinearProgressView">
        <attr name="lp_paintWidth" format="dimension"></attr>
        <attr name="lp_paintColor" format="color"></attr>
        <attr name="lp_textSize" format="dimension"></attr>
        <attr name="lp_type" format="integer"></attr>
    </declare-styleable>

地址:
csdn:http://download.csdn.net/download/qq_38367802/10172775
github:https://github.com/liuzhenhang/myview