自定义圆环 像qq健康里面的圆环(简陋版)

自定义view首当其冲第一步就是去怎么设计  :
在这里附上编写自定义view时的设计  并附上源码    
如果有大牛觉得有不足的地方欢迎来喷 ,嘻嘻嘻

public class StepArecView extends View {


    /**
     * 设计思路:
     *
     * 1,先获取到控件定义的位置大小信息(应为是圆环所以应该为正方形   如果长宽不一致 可以自由选择最大值或者最小值都可  )
     * 2,得到长宽信息后  定义一个准备绘制矩形的对象RectF   (我们绘制的圆环是该矩形的内切圆  所以参数传值的时候需要计算好)
     * 3,开始绘制未加载部分圆环    drawArc       当然圆环不需要内填充 所以我们需要定义画笔Paint的宽度来确定圆环的宽度
     * 4,drawArc  中第二个参数是指起始角度(以180度角为基准 顺时针计算) 第三个参数就是我们需要圆环的总角度最大360
     * 5,开始绘制已加载部分圆环    和绘制未加载圆环一样  不同的是 已加载部分圆环会不断的修改已加载的角度(动效)  当然不带动效的自行路过  可以忽略
     * 6,计算已加载部分圆环的角度     (当前值/总进度值  *最大角度值 )这便是已加载圆环的该显示的角度了
     * 7,绘制矩形文字在圆环中心(自行略过   也就两句代码)
     * 8,然后  就是我们的动画了      这里我们暴露了个方法setCurrentCount给activity调用方便传递总进度值和当前进度值  然后有动画效果的绘制进度值
     *      这里我们用到了ValueAnimator   在addUpdateListener回掉方法中不停的去重新绘制已加载进度值    (不懂可以去看setAnimation方法)
     *
     *
     */

    private float borderWidth=50f;//圆弧的宽度
    private float numberTextSize=13;//字体大小
    private String stepNumber="0";//多少步
    private float startAngle=135;//圆弧的角度
    private float angleLength=270;//整个圆弧划过的角度
    private float currentAngleLength=260;//默认是已加载进度表示的角度

    private  int animationLength=3000;//动画时长

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

    public StepArecView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public StepArecView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

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

        float centerX=getWidth()/2;


        /**
         * 原型内接矩形      圆弧是该巨型的外接圆构成
         */
        RectF rectF=new RectF(0+borderWidth,borderWidth,2*centerX-borderWidth,2*centerX-borderWidth);

        drawArcYello(canvas,rectF);
        drawArcRed(canvas,rectF);
        drawTextValue(canvas,centerX);
    }


    /**
     * 绘制全部进度
     * @param canvas
     * @param rectF
     */
    private void drawArcYello(Canvas canvas, RectF rectF) {
        Paint paint1=new Paint();
        paint1.setColor(Color.YELLOW);
        //设置接口处为圆弧
        paint1.setStrokeJoin(Paint.Join.ROUND);
        paint1.setStrokeCap(Paint.Cap.ROUND);//设置画笔的样式是圆形还是矩形
        paint1.setStyle(Paint.Style.STROKE);
        paint1.setAntiAlias(true);
        paint1.setStrokeWidth(borderWidth);
        canvas.drawArc(rectF,startAngle,angleLength,false,paint1);
    }

    private void drawArcRed(Canvas canvas,RectF rectF){
        Paint paint2=new Paint();
        paint2.setColor(Color.RED);
        //设置接口处为圆弧
        paint2.setStrokeJoin(Paint.Join.ROUND);
        paint2.setStrokeCap(Paint.Cap.ROUND);//设置画笔的样式是圆形还是矩形
        paint2.setStyle(Paint.Style.STROKE);
        paint2.setAntiAlias(true);
        paint2.setStrokeWidth(borderWidth);
        canvas.drawArc(rectF,startAngle,currentAngleLength,false,paint2);
    }
    private void drawTextValue(Canvas canvas,float centerX){

        Paint paint3=new Paint();
        paint3.setTextSize(dipToPx(18));
        paint3.setAntiAlias(true);
        paint3.setTextAlign(Paint.Align.CENTER);
        paint3.setColor(Color.RED);
        String text=String.valueOf(currentAngleLength);
        Rect rect=new Rect();
        paint3.getTextBounds(text,0,text.length(),rect);
        canvas.drawText(text,centerX,getHeight()/2+rect.height(),paint3);


    }


    public void setCurrentCount(int maxCount,int nowCount){
        float scale=(float) nowCount/maxCount;
        setAnimation(0,scale*angleLength,animationLength);

    }
    /**
     * 为进度设置动画
     * ValueAnimator是整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行操作来实现的,
     * 而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。
     * 它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,
     * 我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,
     * 那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。
     *
     * @param last
     * @param current
     */
    private void setAnimation(float last, float current, int length) {
        ValueAnimator progressAnimator = ValueAnimator.ofFloat(last, current);
        progressAnimator.setDuration(length);
        progressAnimator.setTarget(currentAngleLength);
        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentAngleLength = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        progressAnimator.start();
    }
    /**
     * dip 转换成px
     *
     * @param dip
     * @return
     */

    private int dipToPx(float dip) {
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值