Android _自定义芝麻积分(装逼神器)

本文由陈朝勇原创。
陈朝勇的博客地址:
http://blog.csdn.net/ccy0122
本篇文章是我的一个算是做注释的一个博客,废话不多说,开始我们的神器开发.

首先看下我们的效果图,

1. 自定义的控件第一步,(天才第一步….脑补吧),对,你没有看错,就是继承view,并生成三个构造方法.

package cn.yuan.yu.mainmodule.module;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by yukoyuan on 2016/11/30.
 * 这是一个仿制芝麻积分的自定义控件
 */
public class RoundIndicatorView extends View {


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

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

    public RoundIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        setBackgroundColor(0xFFFF6347);
        /**
         * 初始化属性
         */
        initAttr(attrs);
        /**
         * 初始化画笔
         */
        initPaint();
    }

}

2.自定义一些我们可能需要用到的属性


    
    <declare-styleable name="RoundIndicatorView">
        
        <attr name="maxNum" format="integer" />
        
        <attr name="startAngle" format="integer" />
        
        <attr name="sweepAngle" format="integer" />
    declare-styleable>

3.进入属性的初始化.

  /**
         * 活得各项参数合集
         */
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RoundIndicatorView);
        /**
         * 最大的值
         */
        maxNum = array.getInt(R.styleable.RoundIndicatorView_maxNum, 900);
        /**
         * 开始的角度
         */
        startAngle = array.getInt(R.styleable.RoundIndicatorView_startAngle, 160);
        /**
         * 扫过的角度
         */
        sweepAngle = array.getInt(R.styleable.RoundIndicatorView_sweepAngle, 220);
        /**
         * 内部圆的宽度
         */
        sweepInWidth = dp2px(8);
        /**
         * 外部圆的宽度
         */
        sweepOutWidth = dp2px(3);
        /**
         * 释放资源
         */
        array.recycle();

4,进行画笔的初始化


    /**
     * 这是一个初始化画笔的方法
     */
    private void initPaint() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setDither(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(0xffffffff);
        paint_2 = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint_3 = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint_4 = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

5.进入我们自定义控件第二个要走的绘制方法

/**
     * 自定义控件第二个要走的方法
     * 

* measure操作主要用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。 *

* 子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。 * * @param widthMeasureSpec 宽度 * @param heightMeasureSpec 高度 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int wSize = MeasureSpec.getSize(widthMeasureSpec); int wMode = MeasureSpec.getMode(widthMeasureSpec); int hSize = MeasureSpec.getSize(heightMeasureSpec); int hMode = MeasureSpec.getMode(heightMeasureSpec); /** * 对于不是确定值的直接给定300*400的大小 */ if (wMode == MeasureSpec.EXACTLY) { mWidth = wSize; } else { mWidth = dp2px(300); } if (hMode == MeasureSpec.EXACTLY) { mHeight = hSize; } else { mHeight = dp2px(400); } /** * 保存计算结果 */ setMeasuredDimension(mWidth, mHeight); }

6.因为我们不需要再onSizeChanged和onLayout方法做操作,所以直接进入了我们的绘制方法


    /**
     * 自定义控件第五个要走的方法
     *
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /**
         * 角度
         */
        radius = getMeasuredWidth() / 4; //不要在构造方法里初始化,那时还没测量宽高
        /**
         * 初始化画布
         */
        canvas.save();
        canvas.translate(mWidth / 2, (mWidth) / 2);
        /**
         * 画内外圆
         */
        drawRound(canvas);
        /**
         * 画刻度
         */
        drawScale(canvas);
        /**
         * 绘制当前进度值
         */
        drawIndicator(canvas);
        /**
         * 画中间的文字
         */
        drawCenterText(canvas);
        canvas.restore();
    }

7,绘制我们的内外圆

  /**
     * 这是一个画内外圆的方法
     *
     * @param canvas 画布
     */
    private void drawRound(Canvas canvas) {
        canvas.save();
        //内圆
        //设置一下它的透明度,范围是00~ff。
        paint.setAlpha(0x40);
        paint.setStrokeWidth(sweepInWidth);
        RectF rectf = new RectF(-radius, -radius, radius, radius);
        canvas.drawArc(rectf, startAngle, sweepAngle, false, paint);
        //外圆
        paint.setStrokeWidth(sweepOutWidth);
        int w = dp2px(10);
        RectF rectf2 = new RectF(-radius - w, -radius - w, radius + w, radius + w);
        canvas.drawArc(rectf2, startAngle, sweepAngle, false, paint);
        canvas.restore();
    }

8,绘制我们的刻度显示


    /**
     * 这是一个画刻度的方法
     *
     * @param canvas 画布
     */
    private void drawScale(Canvas canvas) {
        canvas.save();
        float angle = (float) sweepAngle / 30;//刻度间隔
        canvas.rotate(-270 + startAngle); //将起始刻度点旋转到正上方(270)
        for (int i = 0; i <= 30; i++) {
            if (i % 6 == 0) {   //画粗刻度和刻度值
                paint.setStrokeWidth(dp2px(2));
                paint.setAlpha(0x70);
                canvas.drawLine(0, -radius - sweepInWidth / 2, 0, -radius + sweepInWidth / 2 + dp2px(1), paint);
                drawText(canvas, i * maxNum / 30 + "", paint);
            } else {         //画细刻度
                paint.setStrokeWidth(dp2px(1));
                paint.setAlpha(0x50);
                canvas.drawLine(0, -radius - sweepInWidth / 2, 0, -radius + sweepInWidth / 2, paint);
            }
            if (i == 3 || i == 9 || i == 15 || i == 21 || i == 27) {  //画刻度区间文字
                paint.setStrokeWidth(dp2px(2));
                paint.setAlpha(0x50);
                drawText(canvas, text[(i - 3) / 6], paint);
            }
            canvas.rotate(angle); //逆时针
        }
        canvas.restore();
    }

    /**
     * 这是一个画字体的方法
     *
     * @param canvas 画布
     * @param text   文字
     * @param paint  画笔
     */
    private void drawText(Canvas canvas, String text, Paint paint) {
        paint.setStyle(Paint.Style.FILL);
        paint.setTextSize(sp2px(8));
        float width = paint.measureText(text); //相比getTextBounds来说,这个方法获得的类型是float,更精确些
        canvas.drawText(text, -width / 2, -radius + dp2px(15), paint);
        paint.setStyle(Paint.Style.STROKE);
    }

9.绘制我们的进度值


    /**
     * 绘制当前进度值
     *
     * @param canvas
     */
    private void drawIndicator(Canvas canvas) {
        canvas.save();
        /**
         *
         */
        paint_2.setStyle(Paint.Style.STROKE);
        int sweep;
        if (currentNum <= maxNum) {
            sweep = (int) ((float) currentNum / (float) maxNum * sweepAngle);
        } else {
            sweep = sweepAngle;
        }
        paint_2.setStrokeWidth(sweepOutWidth);
        Shader shader = new SweepGradient(0, 0, indicatorColor, null);
        paint_2.setShader(shader);
        int w = dp2px(10);
        RectF rectf = new RectF(-radius - w, -radius - w, radius + w, radius + w);
        canvas.drawArc(rectf, startAngle, sweep, false, paint_2);
        float x = (float) ((radius + dp2px(10)) * Math.cos(Math.toRadians(startAngle + sweep)));
        float y = (float) ((radius + dp2px(10)) * Math.sin(Math.toRadians(startAngle + sweep)));
        paint_3.setStyle(Paint.Style.FILL);
        paint_3.setColor(0xffffffff);
        paint_3.setMaskFilter(new BlurMaskFilter(dp2px(3), BlurMaskFilter.Blur.SOLID)); //需关闭硬件加速
        canvas.drawCircle(x, y, dp2px(3), paint_3);
        canvas.restore();
    }

10.绘制中间的文字展示


    /**
     * 绘制控件中间的文字
     *
     * @param canvas 画布
     */
    private void drawCenterText(Canvas canvas) {
        canvas.save();
        paint_4.setStyle(Paint.Style.FILL);
        paint_4.setTextSize(radius / 2);
        paint_4.setColor(0xffffffff);
        canvas.drawText(currentNum + "", -paint_4.measureText(currentNum + "") / 2, 0, paint_4);
        paint_4.setTextSize(radius / 4);
        String content = "信用";
        if (currentNum < maxNum * 1 / 5) {
            content += text[0];
        } else if (currentNum >= maxNum * 1 / 5 && currentNum < maxNum * 2 / 5) {
            content += text[1];
        } else if (currentNum >= maxNum * 2 / 5 && currentNum < maxNum * 3 / 5) {
            content += text[2];
        } else if (currentNum >= maxNum * 3 / 5 && currentNum < maxNum * 4 / 5) {
            content += text[3];
        } else if (currentNum >= maxNum * 4 / 5) {
            content += text[4];
        }
        Rect r = new Rect();
        paint_4.getTextBounds(content, 0, content.length(), r);
        canvas.drawText(content, -r.width() / 2, r.height() + 20, paint_4);
        canvas.restore();

    }

11.设置我们的当刻度值改变的时候进行的动画操作

 /**
     * 设置选择数字之后的动画效果
     *
     * @param num
     */
    public void setCurrentNumAnim(int num) {
        float duration = (float) Math.abs(num - currentNum) / maxNum * 1500 + 500; //根据进度差计算动画时间
        ObjectAnimator anim = ObjectAnimator.ofInt(this, "currentNum", num);
        anim.setDuration((long) Math.min(duration, 2000));
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
                int color = calculateColor(value);
                setBackgroundColor(color);
            }
        });
        anim.start();
    }

    /**
     * 选择颜色
     *
     * @param value
     * @return
     */
    private int calculateColor(int value){
        ArgbEvaluator evealuator = new ArgbEvaluator();
        float fraction = 0;
        int color = 0;
        if(value <= maxNum/2){
            fraction = (float)value/(maxNum/2);
            color = (int) evealuator.evaluate(fraction,0xFFFF6347,0xFFFF8C00); //由红到橙
        }else {
            fraction = ( (float)value-maxNum/2 ) / (maxNum/2);
            color = (int) evealuator.evaluate(fraction,0xFFFF8C00,0xFF00CED1); //由橙到蓝
        }
        return color;
    }

ok,到此我们的自定义芝麻积分就到此完成了.感谢大家.

你可能感兴趣的:(android,芝麻积分,支付宝,自定义控件,Android自定义View)