2018-03-21尾部有圆圈的progressbar

最近整理blog把所有博客都整理到简书上,这是一个自定义view


效果如下
效果如下

纠结了很久网上各种找也没找到效果差不多,索性就自己自定义了一个,分享一下。
很多人可能用过ProgressWheel这个第三方的progressbar但是它的尾部没有圆圈,那就按照它来改写吧:先讲下我的思路,我花了四个圆圈,同一个圆心这样的话只要半径不同就可以勾勒出不同的区域显示不同的颜色,最后的那个bar的颜色就直接按照弧度来划,下面上代码。

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.Html;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * Created by Administrator on 2016/6/7.
 */
public class MyProgressBar extends View {
    //Sizes (with defaults)
    private int layoutHeight = 0;
    private int layoutWidth = 0;
    //Padding (with defaults)
    private int paddingTop = 5;
    private int paddingBottom = 5;
    private int paddingLeft = 5;
    private int paddingRight = 5;
    private String[] splitText = {"测试"};

    private RectF one_rectf = new RectF();

    private RectF two_rectf = new RectF();
    private RectF three_rectf = new RectF();
    private RectF four_rectf = new RectF();
    private RectF bar_rectf = new RectF();


    private int bar_color = 0xFFFEA049;
    private int rim_color = 0xFFD9D9D9;
    private int three_color = 0xFFFFDBB9;
    private int four_color = 0xFFFEA049;

    //Paints
    private Paint barPaint = new Paint();
    private Paint onePaint = new Paint();
    private Paint twoPaint = new Paint();
    private Paint threePaint = new Paint();
    private Paint fourPaint = new Paint();
    private Paint ciclePaint = new Paint();
    private Paint textPaint = new Paint();


    private float progress = 0f;

    public MyProgressBar(Context context) {
        super(context);
    }

    public MyProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /*
   * When this is called, make the view square.
   *onmeasure方法是ProgressWheel的我没有动,我看主要的意思就是在不算上padding的时候把这个view弄成一个正方形
   */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // The first thing that happen is that we call the superclass
        // implementation of onMeasure. The reason for that is that measuring
        // can be quite a complex process and calling the super method is a
        // convenient way to get most of this complexity handled.
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // We can’t use getWidth() or getHight() here. During the measuring
        // pass the view has not gotten its final size yet (this happens first
        // at the start of the layout pass) so we have to use getMeasuredWidth()
        // and getMeasuredHeight().
        int size = 0;
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
        int heightWithoutPadding = height - getPaddingTop() - getPaddingBottom();

        // Finally we have some simple logic that calculates the size of the view
        // and calls setMeasuredDimension() to set that size.
        // Before we compare the width and height of the view, we remove the padding,
        // and when we set the dimension we add it back again. Now the actual content
        // of the view will be square, but, depending on the padding, the total dimensions
        // of the view might not be.
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if (heightMode != MeasureSpec.UNSPECIFIED && widthMode != MeasureSpec.UNSPECIFIED) {
            if (widthWithoutPadding > heightWithoutPadding) {
                size = heightWithoutPadding;
            } else {
                size = widthWithoutPadding;
            }
        } else {
            size = Math.max(heightWithoutPadding, widthWithoutPadding);
        }


        // If you override onMeasure() you have to call setMeasuredDimension().
        // This is how you report back the measured size.  If you don’t call
        // setMeasuredDimension() the parent will throw an exception and your
        // application will crash.
        // We are calling the onMeasure() method of the superclass so we don’t
        // actually need to call setMeasuredDimension() since that takes care
        // of that. However, the purpose with overriding onMeasure() was to
        // change the default behaviour and to do that we need to call
        // setMeasuredDimension() with our own values.
        setMeasuredDimension(
                size + getPaddingLeft() + getPaddingRight(),
                size + getPaddingTop() + getPaddingBottom());
    }

//这个方法是当view的size变化的时候调用
    @Override
    protected void onSizeChanged(int newWidth, int newHeight, int oldWidth, int oldHeight) {
        super.onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
        layoutWidth = newWidth;
        layoutHeight = newHeight;
        setupBounds();
        setupPaints();
        invalidate();
    }

    private void setupPaints() {
        barPaint.setColor(bar_color);
        barPaint.setAntiAlias(true);
        barPaint.setStyle(Paint.Style.STROKE);
        barPaint.setStrokeWidth(10);


        onePaint.setColor(rim_color);
        onePaint.setAntiAlias(true);
        onePaint.setStyle(Paint.Style.FILL);
//        onePaint.setStrokeWidth(10);


        twoPaint.setColor(Color.WHITE);
        twoPaint.setAntiAlias(true);
        twoPaint.setStyle(Paint.Style.FILL);
//        twoPaint.setStrokeWidth(10);


        threePaint.setColor(three_color);
        threePaint.setAntiAlias(true);
        threePaint.setStyle(Paint.Style.FILL);
//        threePaint.setStrokeWidth(10);


        fourPaint.setColor(four_color);
        fourPaint.setAntiAlias(true);
        fourPaint.setStyle(Paint.Style.FILL);
//        fourPaint.setStrokeWidth(10);

        ciclePaint.setColor(four_color);
        ciclePaint.setAntiAlias(true);
        ciclePaint.setStyle(Paint.Style.FILL);


        textPaint.setColor(Color.WHITE);
        textPaint.setAntiAlias(true);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setTextSize(40);

    }


    private void setupBounds() {
        one_rectf = new RectF(paddingLeft + 10, paddingTop + 10, layoutWidth - paddingRight - 10, layoutHeight - paddingBottom - 10);
        two_rectf = new RectF(paddingLeft + 20, paddingTop + 20, layoutWidth - paddingRight - 20, layoutHeight - paddingBottom - 20);
        three_rectf = new RectF(paddingLeft + 60, paddingTop + 60, layoutWidth - paddingRight - 60, layoutHeight - paddingBottom - 60);
        four_rectf = new RectF(paddingLeft + 90, paddingTop + 90, layoutWidth - paddingRight - 90, layoutHeight - paddingBottom - 90);
        bar_rectf = new RectF(paddingLeft + 15, paddingTop + 15, layoutWidth - paddingRight - 15, layoutHeight - paddingBottom - 15);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawArc(one_rectf, 360, 360, true, onePaint);
        canvas.drawArc(two_rectf, 360, 360, false, twoPaint);
        canvas.drawArc(three_rectf, 360, 360, false, threePaint);
        canvas.drawArc(four_rectf, 360, 360, false, fourPaint);
        canvas.drawArc(bar_rectf, -90, (((progress / 100f)) * 360f), false, barPaint);
        float reduin = one_rectf.centerX() - paddingLeft;
        for (String line : splitText) {
            float horizontalTextOffset = textPaint.measureText(line) / 2;
            canvas.drawText(
                    line + "\n",
                    layoutWidth / 2 - horizontalTextOffset,
                    layoutHeight / 2,
                    textPaint);
        }

        canvas.save();
        canvas.rotate(((progress / 100f)) * 360f, one_rectf.centerX(), one_rectf.centerY());
        canvas.drawCircle((float) (one_rectf.centerX()), (float) (one_rectf.centerY() - reduin + 15), 20, ciclePaint);

    }

    /**
     * Set the progress to a specific value
     */
    public void setProgress(float i) {
//        isSpinning = false;
        progress = (float) i;
        postInvalidate();
    }
}

下面就是xml里面的内容:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff">
    <www.prograssbar.com.MyProgressBar
        android:id="@+id/prograssbar"
        android:layout_width="200dp"
        android:layout_height="200dp" />
</RelativeLayout>

下面是activity里面的内容:

import android.animation.ValueAnimator;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    private MyProgressBar progressWheel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        progressbar= (MyProgressBar) findViewById(R.id.prograssbar);
        //添加一个属性动画,如果对属性动画不是太了解的可以阅读鸿神的博客[](http://blog.csdn.net/lmj623565791/article/details/38067475)
        ValueAnimator valueAnimator2 = ValueAnimator.ofFloat(0, 30);
        valueAnimator2.setDuration(1000);
        valueAnimator2.start();
        valueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                progressbar.setProgress((Float) animation.getAnimatedValue());
            }
        });
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容