自定義view - 進度條

madreain發表於2017-09-21

廢話不多說先看效果圖

效果圖
效果圖

原諒模擬器顯示的不好看,為了錄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地址

相關文章