自定義view - 炫酷進(jìn)度條

1. 思路分析


自定義View步驟:
1>:values__attrs.xml跺株,自定義屬性跷睦;
2>:在第三個(gè)構(gòu)造方法中缚够,獲取自定義屬性娶聘;
3>:onMeasure:不是非必須的,測(cè)量控件大谐饴恕将鸵;
4>:onDraw:所有繪制代碼都寫在onDraw方法中;

思路分析
1>:自定義屬性:內(nèi)圓顏色佑颇、外圓顏色顶掉、圓弧寬度、中間文字顏色挑胸、文字大醒魍病;
2>:自定義ProgressBar茬贵,繼承View簿透;

2. 效果圖如下


圖片.png

3. 代碼如下


1>:attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- 炫酷進(jìn)度條 -->
    <declare-styleable name="ProgressBar">
        <!-- 內(nèi)圓弧背景 -->
        <attr name="innerBackground" format="color"/>
        <!-- 外圓弧背景 -->
        <attr name="outterBackground" format="color"/>
        <!-- 圓弧寬度 -->
        <attr name="roundWidth" format="dimension"/>
        <!-- 文字大小 -->
        <attr name="progressTextSize" format="dimension"/>
        <!-- 文字顏色 -->
        <attr name="progressTextColor" format="color"/>
    </declare-styleable>
</resources>
2>:ProgressBar
/**
 * ================================================
 * Email: 2185134304@qq.com
 * Created by Novate 2018/12/29 15:25
 * Version 1.0
 * Params:
 * Description:    圓形進(jìn)度條
 * ================================================
*/

public class ProgressBar extends View {

    // 內(nèi)圓弧默認(rèn)顏色
    private int mInnerBackground = Color.RED ;
    // 外圓弧默認(rèn)顏色
    private int mOuterBackground = Color.RED;
    // 圓弧寬度
    private int mRoundWidth = 10 ;
    // 文字大小
    private float mProgressTextSize = 15 ;
    // 文字顏色
    private int mProgressTextColor = Color.RED;

    // 3個(gè)畫筆 內(nèi)圓弧畫筆、外圓弧畫筆解藻、文字畫筆
    private Paint mInnerPaint,mOuterPaint,mTextPaint;

    // 設(shè)置最大進(jìn)度
    private int mMax = 100 ;
    // 當(dāng)前進(jìn)度
    private int mProgress = 0 ;
    // 百分比
    private float  persent ;

    public ProgressBar(Context context) {
        this(context,null);
    }

    public ProgressBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public ProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        // 獲取自定義屬性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ProgressBar);
        // 內(nèi)圓弧背景
        mInnerBackground = typedArray.getColor(R.styleable.ProgressBar_innerBackground,mInnerBackground);
        // 外圓弧背景
        mOuterBackground = typedArray.getColor(R.styleable.ProgressBar_outterBackground,mOuterBackground);
        // 圓弧寬度
        mRoundWidth = typedArray.getDimensionPixelSize(R.styleable.ProgressBar_roundWidth,(int)dip2px(mRoundWidth));
        // 文字大小
        mProgressTextSize = typedArray.getDimensionPixelSize(R.styleable.ProgressBar_progressTextSize,sp2px(mProgressTextSize));
        // 文字顏色
        mProgressTextColor = typedArray.getColor(R.styleable.ProgressBar_progressTextColor,mProgressTextColor);
        // 釋放資源
        typedArray.recycle();


        // 初始化3個(gè)畫筆
        initPaint();
    }

    private void initPaint() {
        // 內(nèi)圓弧畫筆
        mInnerPaint = new Paint();
        // 設(shè)置抗鋸齒
        mInnerPaint.setAntiAlias(true);
        // 內(nèi)圓弧顏色
        mInnerPaint.setColor(mInnerBackground);
        // 圓弧寬度
        mInnerPaint.setStrokeWidth(mRoundWidth);
        // 只繪制圖形邊緣(描邊) Paint.Style.FILL 只繪制圖形內(nèi)容 Paint.Style.FILL_AND_STROKE 既繪制輪廓也繪制內(nèi)容
        mInnerPaint.setStyle(Paint.Style.STROKE);

        //外圓弧畫筆
        mOuterPaint = new Paint() ;
        mOuterPaint.setAntiAlias(true);
        mOuterPaint.setColor(mOuterBackground);
        mOuterPaint.setStrokeWidth(mRoundWidth); //設(shè)置圓弧寬度
        mOuterPaint.setStyle(Paint.Style.STROKE);

        //文字畫筆
        mTextPaint = new Paint() ;
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(mProgressTextSize);
        mTextPaint.setColor(mProgressTextColor);
    }


    /**
     * 測(cè)量控件大小
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 與qq計(jì)步器一樣老充,只寫最簡(jiǎn)單的形式,直接獲取寬高螟左,也就是說對(duì)應(yīng)到xml布局文件中的寬高屬性只能設(shè)置固定值啡浊,
        // 不能是wrap_content,如果想要設(shè)置wrap_content胶背,這里首先要獲取寬高模式巷嚣,然后根據(jù)寬高模式再去獲取寬高

        int width = MeasureSpec.getSize(widthMeasureSpec) ;
        int height = MeasureSpec.getSize(heightMeasureSpec) ;

        // 測(cè)量大小 這里保證是正方形:下邊2種方式
//        setMeasuredDimension(width>height?height:width,width>height?height:width);
        setMeasuredDimension(Math.min(width, height), Math.min(width, height));
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 1. 畫內(nèi)圓[是圓形,不是圓弧]
        drawCircle(canvas) ;

        // 2. 畫外圓弧
        drawArc(canvas) ;

        // 3. 畫文字
        drawText(canvas) ;
    }


    /**
     * 畫文字
     */
    private void drawText(Canvas canvas) {
        // 要畫的文字
        String text = (int)(persent*100)+"%";
        Rect rect = new Rect();
        // 文字區(qū)域
        mTextPaint.getTextBounds(text,0,text.length(),rect);

        int dx = getWidth()/2 - rect.width()/2;

        Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
        int dy = (fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.bottom;
        // 基線
        int baseLine = getHeight()/2+dy;
        canvas.drawText(text,dx,baseLine,mTextPaint);
    }


    /**
     * 設(shè)置最大進(jìn)度
     */
    public synchronized void setMax(int max){
        this.mMax=max;
    }

    /**
     * 當(dāng)前進(jìn)度
     */
    public synchronized void setProgress(int progress){
        if (progress < 0){

        }
        this.mProgress=progress;

        // 不斷的獲取到當(dāng)前進(jìn)度钳吟,然后需要不斷的刷新
        invalidate();
    }


    /**
     * 2. 畫外圓弧廷粒, 固定寫法
     */
    private void drawArc(Canvas canvas) {
        RectF rectF = new RectF(0+mRoundWidth/2,0+mRoundWidth/2,getWidth()-mRoundWidth/2,getHeight()-mRoundWidth/2);
        if (mProgress == 0)
            return;

        persent = (float)mProgress/mMax;

        // param1: 圓弧形狀和大小范圍 param2: 開始的角度 param3: 掃過的角度 params4: 設(shè)置在畫圓弧的時(shí)候,是否經(jīng)過圓形 param5: 畫筆
        canvas.drawArc(rectF,0,persent*360,false,mOuterPaint);
    }


    /**
     * 1. 畫內(nèi)圓:是圓形砸抛,不是圓弧, 固定寫法
     */
    private void drawCircle(Canvas canvas) {
        // 中心點(diǎn)
        int center = getWidth()/2;
        // param1:圓心x坐標(biāo) param2:圓心y坐標(biāo) param3:圓的半徑 param4: 畫筆
        canvas.drawCircle(center,center,center-mRoundWidth/2,mInnerPaint);
    }

    private int sp2px(float sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
    }

    private float dip2px(int dip) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
    }
}
3>:activity_progressbar
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.novate.test.customview.ProgressBar
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:innerBackground="@color/colorPrimary"
        app:outterBackground="@color/colorAccent"
        app:roundWidth="20dp"
        app:progressTextColor="@color/colorAccent"
        app:progressTextSize="20sp"
        android:id="@+id/progress_bar"
        />
</LinearLayout>
4>:ProgressBarActivity
public class ProgressBarActivity extends AppCompatActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_progressbar);

        final ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
        // 設(shè)置最大進(jìn)度
        mProgressBar.setMax(4000);

        // 屬性動(dòng)畫
        ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0,4000);
        valueAnimator.setDuration(2000);
        valueAnimator.start();
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 不斷的獲取當(dāng)前進(jìn)度
                float currrentProgress = (float) animation.getAnimatedValue();
                // 設(shè)置當(dāng)前進(jìn)度
                mProgressBar.setProgress((int) currrentProgress);
            }
        });
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末树枫,一起剝皮案震驚了整個(gè)濱河市直焙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砂轻,老刑警劉巖奔誓,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡厨喂,警方通過查閱死者的電腦和手機(jī)和措,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜕煌,“玉大人派阱,你說我怎么就攤上這事⌒奔停” “怎么了贫母?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長盒刚。 經(jīng)常有香客問我腺劣,道長,這世上最難降的妖魔是什么因块? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任橘原,我火速辦了婚禮,結(jié)果婚禮上涡上,老公的妹妹穿的比我還像新娘趾断。我一直安慰自己,他們只是感情好吓懈,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布歼冰。 她就那樣靜靜地躺著,像睡著了一般耻警。 火紅的嫁衣襯著肌膚如雪隔嫡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天甘穿,我揣著相機(jī)與錄音腮恩,去河邊找鬼。 笑死温兼,一個(gè)胖子當(dāng)著我的面吹牛秸滴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播募判,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼荡含,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了届垫?” 一聲冷哼從身側(cè)響起释液,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎装处,沒想到半個(gè)月后误债,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年寝蹈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了李命。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡箫老,死狀恐怖封字,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情槽惫,我是刑警寧澤周叮,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站界斜,受9級(jí)特大地震影響仿耽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜各薇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一项贺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧峭判,春花似錦开缎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至疗认,卻和暖如春完残,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背横漏。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工谨设, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缎浇。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓扎拣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親素跺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子二蓝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容