关于一些自定义控件的记录

一个三环评分控件

效果:

test.gif

代码:

  <declare-styleable name="ScoreCircleView">
        <attr name="sbackWidth" format="dimension" />    <!--背景圆环宽度-->
        <attr name="sprogWidth" format="dimension" />    <!--进度圆环宽度-->
        <attr name="sbackColor" format="color" />        <!--背景圆环颜色-->
        <attr name="sprogTextColor" format="color" />
        <attr name="sprogTextSize" format="dimension" />
        <attr name="sprogStartColor" format="color" />   <!--进度圆环开始颜色-->
        <attr name="sprogFirstColor" format="color" />   <!--进度圆环结束颜色-->
        <attr name="sprogOneColor" format="color" />   <!--进度圆环结束颜色-->
        <attr name="sprogTwoColor" format="color" />   <!--进度圆环结束颜色-->
        <attr name="sprogThreeColor" format="color" />   <!--进度圆环结束颜色-->
        <attr name="sprogress" format="integer" />       <!--圆环进度-->
    </declare-styleable>
public class ScoreCircleView extends View {

    private Paint mBackPaint, mProgPaint,mTextPaint;   // 绘制画笔
    private RectF mRectF;       // 绘制区域
    private int[] mColorArray;  // 圆环渐变色
    public float mTextWidth;
    public float mTextHeight;

    public int POneColor;
    public int PTwoColor;
    public int PThreeColor;
    public ScoreCircleView(Context context) {
        this(context, null);
    }

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

    public ScoreCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        @SuppressLint("Recycle")
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScoreCircleView);

        POneColor=typedArray.getColor(R.styleable.ScoreCircleView_sprogOneColor, Color.BLUE);
        PTwoColor=typedArray.getColor(R.styleable.ScoreCircleView_sprogTwoColor, Color.BLUE);
        PThreeColor=typedArray.getColor(R.styleable.ScoreCircleView_sprogThreeColor, Color.BLUE);
        // 初始化背景圆环画笔
        mBackPaint = new Paint();
        mBackPaint.setStyle(Paint.Style.STROKE);    // 只描边,不填充
        mBackPaint.setStrokeCap(Paint.Cap.ROUND);   // 设置圆角
        mBackPaint.setAntiAlias(true);              // 设置抗锯齿
        mBackPaint.setDither(true);                 // 设置抖动
        mBackPaint.setStrokeWidth(typedArray.getDimension(R.styleable.ScoreCircleView_sbackWidth, 5));
        mBackPaint.setColor(typedArray.getColor(R.styleable.ScoreCircleView_sbackColor, Color.LTGRAY));

        // 初始化进度圆环画笔
        mProgPaint = new Paint();
        mProgPaint.setStyle(Paint.Style.STROKE);    // 只描边,不填充
        mProgPaint.setStrokeCap(Paint.Cap.ROUND);   // 设置圆角
        mProgPaint.setAntiAlias(true);              // 设置抗锯齿
        mProgPaint.setDither(true);                 // 设置抖动
        mProgPaint.setStrokeWidth(typedArray.getDimension(R.styleable.ScoreCircleView_sprogWidth, 10));

        //初始化文本
        mTextPaint=new Paint();
        mTextPaint.setTextAlign(Paint.Align.RIGHT);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setAntiAlias(true);            // 设置抗锯齿
        mTextPaint.setDither(true);                 // 设置抖动
        mTextPaint.setTextSize(typedArray.getDimension(R.styleable.ScoreCircleView_sprogTextSize,16));
        mTextPaint.setColor(typedArray.getColor(R.styleable.ScoreCircleView_sprogTextColor, Color.BLACK));



        // 初始化进度圆环渐变色
        int startColor = typedArray.getColor(R.styleable.ScoreCircleView_sprogStartColor, -1);
        int firstColor = typedArray.getColor(R.styleable.ScoreCircleView_sprogFirstColor, -1);
        if (startColor != -1 && firstColor != -1) mColorArray = new int[]{startColor, firstColor};
        else mColorArray = null;


        typedArray.recycle();

        init();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int viewWide = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
        int viewHigh = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
        int mRectLength = (int) ((viewWide > viewHigh ? viewHigh : viewWide) - (mBackPaint.getStrokeWidth() > mProgPaint.getStrokeWidth() ? mBackPaint.getStrokeWidth() : mProgPaint.getStrokeWidth()));
        int mRectL = getPaddingLeft() + (viewWide - mRectLength) / 2;
        int mRectT = getPaddingTop() + (viewHigh - mRectLength) / 2;
        mRectF = new RectF(mRectL, mRectT, mRectL + mRectLength, mRectT + mRectLength);

//        // 设置进度圆环渐变色
//        if (mColorArray != null && mColorArray.length > 1)
//            mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));
//
    }

    int mStrokWidth=dp2px(30);
    int mTextMargin=dp2px(18);
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawArc(mRectF, 270,270 , false, mBackPaint);
        canvas.drawArc(mRectF.left+mStrokWidth,mRectF.top+mStrokWidth,mRectF.right-mStrokWidth,mRectF.bottom-mStrokWidth,270,270,false,mBackPaint);
        canvas.drawArc(mRectF.left+mStrokWidth*2,mRectF.top+mStrokWidth*2,mRectF.right-mStrokWidth*2,mRectF.bottom-mStrokWidth*2,270,270,false,mBackPaint);

        for (int i = 0; i < list.size(); i++) {
            if (i==0){
                mProgPaint.setColor(getProgressColor(i));
                canvas.drawArc(mRectF, 270, 270 *presont*list.get(i).getValues() / 100, false, mProgPaint);

            }else
            {
                mProgPaint.setColor(getProgressColor(i));

                canvas.drawArc(mRectF.left+mStrokWidth*i,mRectF.top+mStrokWidth*i,mRectF.right-mStrokWidth*i,mRectF.bottom-mStrokWidth*i,270,270 *presont*list.get(i).getValues() / 100,false,mProgPaint);

            }

        }

        for (int i = 0; i < list.size(); i++) {
            Rect rect = new Rect();
            mTextPaint.getTextBounds(list.get(i).getName(),0,list.get(i).getName().length(),rect);
            int textHeight = rect.height()/4;
            canvas.drawText(list.get(i).getName(),getMeasuredWidth()/2-mTextMargin,mRectF.top+mStrokWidth*i+textHeight,mTextPaint);

        }
    }



    /**
     * 初始化界面
     */
    public void init() {

        ValueItem item1=new ValueItem("力度",00);
        ValueItem item2=new ValueItem("时长",00);
        ValueItem item3=new ValueItem("区域",00);
        ArrayList<ValueItem> objects = new ArrayList<>();
        objects.add(item1);
        objects.add(item2);
        objects.add(item3);
        setValues(objects,3000);
    }

    /**
     * 返回对应的样色
     * @param i
     * @return
     */
    public int getProgressColor(int i){
        switch (i){
            case 0:
                return POneColor;
            case 1:
                return PTwoColor;

            case 2:
                return PThreeColor;

        }

        return POneColor;
    }


    /**
     * dp转px
     */
    private int dp2px(float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getContext().getResources().getDisplayMetrics());
    }


    /**
     * 设置背景圆环颜色
     *
     * @param color 背景圆环颜色
     */
    public void setBackColor(@ColorRes int color) {
        mBackPaint.setColor(ContextCompat.getColor(getContext(), color));
        invalidate();
    }

    /**
     * 设置进度圆环宽度
     *
     * @param width 进度圆环宽度
     */
    public void setProgWidth(int width) {
        mProgPaint.setStrokeWidth(width);
        invalidate();
    }
    float presont=0;
    List<ValueItem> list=new ArrayList<>();
    public void setValues(List<ValueItem> list,long animTime){
        this.list=list;
        if (animTime <= 0) {

        }
        else {
            ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                     presont = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            animator.setInterpolator(new OvershootInterpolator());
            animator.setDuration(animTime);
            animator.start();
        }

    }



    /**
     * 设置进度圆环颜色(支持渐变色)
     *
     * @param startColor 进度圆环开始颜色
     * @param firstColor 进度圆环结束颜色
     */
    public void setProgColor(@ColorRes int startColor, @ColorRes int firstColor) {
        mColorArray = new int[]{ContextCompat.getColor(getContext(), startColor), ContextCompat.getColor(getContext(), firstColor)};
        mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));
        invalidate();
    }

    /**
     * 设置进度圆环颜色(支持渐变色)
     *
     * @param colorArray 渐变色集合
     */
    public void setProgColor(@ColorRes int[] colorArray) {
        if (colorArray == null || colorArray.length < 2) return;
        mColorArray = new int[colorArray.length];
        for (int index = 0; index < colorArray.length; index++)
            mColorArray[index] = ContextCompat.getColor(getContext(), colorArray[index]);
        mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));
        invalidate();
    }

    public class ValueItem{
        String name;
        float values;

        public ValueItem(String name, float values) {
            this.name = name;
            this.values = values;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public float getValues() {
            return values;
        }

        public void setValues(float values) {
            this.values = values;
        }
    }

一个中心扩散雷达 控件

效果


teszt.gif

代码

public class WaterWave extends View {
    private float mInitialRadius;   // 初始波纹半径
    private float mMaxRadiusRate = 0.95f;   // 如果没有设置mMaxRadius,可mMaxRadius = 最小长度 * mMaxRadiusRate;
    private float mMaxRadius;   // 最大波纹半径
    private long mDuration = 3000; // 一个波纹从创建到消失的持续时间
    private int mSpeed = 800;   // 波纹的创建速度,每500ms创建一个
    private Interpolator mInterpolator = new LinearInterpolator();

    private List<Circle> mCircleList = new ArrayList<Circle>();
    private boolean mIsRunning;

    private boolean mMaxRadiusSet;

    private Paint mPaint;
    private long mLastCreateTime;

    private Runnable mCreateCircle = new Runnable() {
        @Override
        public void run() {
            if (mIsRunning) {
                newCircle();
                postDelayed(mCreateCircle, mSpeed);
            }
        }
    };

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

    public WaterWave(Context context, AttributeSet attrs) {
        super(context, attrs);

        init();

    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        setStyle(Paint.Style.FILL);
//        mPaint.setStrokeWidth(4);
        mPaint.setColor(Color.parseColor("#3F3F51"));
    }

    public void setStyle(Paint.Style style) {
        mPaint.setStyle(style);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (!mMaxRadiusSet) {
            mMaxRadius = Math.min(w, h) * mMaxRadiusRate / 2.0f;
        }
        start();
    }

    public void setMaxRadiusRate(float maxRadiusRate) {
        this.mMaxRadiusRate = maxRadiusRate;
    }

    public void setColor(int color) {
        mPaint.setColor(color);
    }

    /**
     * 开始
     */
    public void start() {
        if (!mIsRunning) {
            mIsRunning = true;

            mCreateCircle.run();
        }
    }

    /**
     * 停止
     */
    public void stop() {
        mIsRunning = false;
    }

    protected void onDraw(Canvas canvas) {
        Iterator<Circle> iterator = mCircleList.iterator();
        while (iterator.hasNext()) {
            Circle circle = iterator.next();
            if (System.currentTimeMillis() - circle.mCreateTime < mDuration) {
                mPaint.setAlpha(circle.getAlpha());
                mPaint.setShader(new RadialGradient(getWidth() / 2,getHeight() / 2,circle.getCurrentRadius(),new int[]{0xFFBC60C4,0xFF5C63FA},new float[]{0.3f,0.8f}, Shader.TileMode.CLAMP));
                canvas.drawCircle(getWidth() / 2, getHeight() / 2, circle.getCurrentRadius(), mPaint);
            } else {
                iterator.remove();
            }

        }
        if (mCircleList.size() > 0) {
            postInvalidateDelayed(10);
        }
    }

    public void setInitialRadius(float radius) {
        mInitialRadius = radius;
    }

    public void setDuration(long duration) {
        this.mDuration = duration;
    }

    public void setMaxRadius(float maxRadius) {
        this.mMaxRadius = maxRadius;
        mMaxRadiusSet = true;
    }

    public void setSpeed(int speed) {
        mSpeed = speed;
    }

    private void newCircle() {
        long currentTime = System.currentTimeMillis();
        if (currentTime - mLastCreateTime < mSpeed) {
            return;
        }
        Circle circle = new Circle();
        mCircleList.add(circle);
        invalidate();
        mLastCreateTime = currentTime;
    }

    private class Circle {
        private long mCreateTime;

        public Circle() {
            this.mCreateTime = System.currentTimeMillis();
        }

        public int getAlpha() {
            float percent = (System.currentTimeMillis() - mCreateTime) * 1.0f / mDuration;
            return (int) ((1.0f - mInterpolator.getInterpolation(percent)) * 255);
        }

        public float getCurrentRadius() {
            float percent = (System.currentTimeMillis() - mCreateTime) * 1.0f / mDuration;
            return mInitialRadius + mInterpolator.getInterpolation(percent) * (mMaxRadius - mInitialRadius);
        }
    }

    public void setInterpolator(Interpolator interpolator) {
        mInterpolator = interpolator;
        if (mInterpolator == null) {
            mInterpolator = new LinearInterpolator();
        }
    }

}

一个 带分数的进度条 自定义控件

效果:


zzt.gif

代码:

public class ProgressBar extends View implements View.OnClickListener {
    private String TAG = this.getClass().getName();

    public UsmileProgressBar(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);
        init();
    }


    Paint mBarPaint;
    Paint mBarBgPaint;
    Paint mRriangPaint;//三角形
    Paint mTextPaint;//文字
    Path mRriangPath;
    int BasePadding = dipToPx(getContext(), 10);

    private void init() {
        mBarBgPaint = new Paint();
        mBarBgPaint.setStyle(Paint.Style.FILL);
        mBarBgPaint.setColor(Color.parseColor("#222329"));

        mBarPaint = new Paint();
        mBarPaint.setStyle(Paint.Style.FILL);
        mRriangPaint = new Paint();
        mRriangPaint.setStyle(Paint.Style.FILL);
        mRriangPaint.setColor(Color.BLUE);
        mTextPaint = new Paint();
        mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
        mRriangPath = new Path();
        setOnClickListener(this);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        setValues(100, true);

    }

    int DefWidth = dipToPx(getContext(), 240);
    int DefHeight = dipToPx(getContext(), 50);

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int sizeWith = MeasureSpec.getSize(widthMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);

        //根据模式来 决定宽度
        switch (modeWidth) {

            case MeasureSpec.EXACTLY://match_parent  精确的度数
                DefWidth = sizeWith;
                break;
            case MeasureSpec.AT_MOST://wrap_content  适配的度数


                break;
        }


        //根据模式来 决定宽度
        switch (modeHeight) {

            case MeasureSpec.EXACTLY://match_parent  精确的度数
                DefHeight = sizeHeight;
                break;
            case MeasureSpec.AT_MOST://wrap_content  适配的度数


                break;
        }


        setMeasuredDimension(DefWidth, DefHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);
        drawLable(canvas);
        drawSorce(canvas);
        drawRriang(canvas);
        drawProgress(canvas);


    }

    String LableSorce = "80分";

    private void drawSorce(Canvas canvas) {

        float mtextHeight = (mTextPaint.getFontMetrics().bottom - mTextPaint.getFontMetrics().top) / 2;
        mTextPaint.setTextAlign(Paint.Align.CENTER);

        mTextPaint.setTextSize(24f);
        mTextPaint.setColor(Color.WHITE);
        canvas.drawText(LableSorce, BarLenght - BasePadding, getHeight() / 2 - BarHeigth / 2 - mtextHeight, mTextPaint);

    }

    String LableStart = "0分";
    String LableEnd = "100分";
    int textHeight = 24;


    private void drawLable(Canvas canvas) {


        mTextPaint.setTextAlign(Paint.Align.LEFT);
        mTextPaint.setTextSize(24f);
        mTextPaint.setColor(Color.parseColor("#83838C"));
        canvas.drawText(LableStart, 0 + BasePadding, getHeight() / 2 + BarHeigth / 2 + textHeight, mTextPaint);
        mTextPaint.setTextAlign(Paint.Align.RIGHT);

        canvas.drawText(LableEnd, getWidth() - BasePadding, getHeight() / 2 + BarHeigth / 2 + textHeight, mTextPaint);

    }


    //    三角形
    int mRriangHeight = dipToPx(getContext(), 10);
    int mRriangWidth = dipToPx(getContext(), 14);

    //绘制三角形
    private void drawRriang(Canvas canvas) {


        mRriangPath.reset();

        mRriangPath.moveTo(BarLenght + BasePadding, getHeight() / 2 + BarHeigth / 2);
        mRriangPath.lineTo(BarLenght + mRriangWidth / 2 + BasePadding, getHeight() / 2 + BarHeigth / 2 + mRriangHeight);
        mRriangPath.lineTo(BarLenght - mRriangWidth / 2 + BasePadding, getHeight() / 2 + BarHeigth / 2 + mRriangHeight);
        mRriangPath.close();


        canvas.drawPath(mRriangPath, mRriangPaint);

    }


    int BarHeigth = dipToPx(getContext(), 10);


    //进度长度
    float BarLenght = 180;

    private void drawProgress(Canvas canvas) {


        RectF rectFBg = new RectF(0 + BasePadding, (getHeight() - BarHeigth) / 2, getWidth() - BasePadding, (getHeight() - BarHeigth) / 2 + BarHeigth);
        canvas.drawRoundRect(rectFBg, 20, 20, mBarBgPaint);

        mBarPaint.setShader(new LinearGradient(0f, 0f, getWidth(), 0f, new int[]{0xFF4E90FC, 0xFF2C7BFB, 0xFF3984FD}, new float[]{0f, 0.5f, 0.9f}, CLAMP));

        RectF rectF = new RectF(0 + BasePadding, (getHeight() - BarHeigth) / 2, BarLenght + BasePadding, (getHeight() - BarHeigth) / 2 + BarHeigth);

        canvas.drawRoundRect(rectF, 20, 20, mBarPaint);

    }


    /**
     * dip 转换成px
     *
     * @param dip
     * @return
     */
    public static int dipToPx(Context context, float dip) {
        float density = context.getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
    }

    ValueAnimator animator;

    public void setValues(float values, boolean isAnimation) {

        Log.i(TAG, "setValues: width:" + getWidth());
        if (isAnimation) {
            if (animator != null) {
                animator.cancel();
                animator.setFloatValues(0, values);
                animator.start();
            } else {
                animator = ValueAnimator.ofFloat(0f, values);
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator valueAnimator) {

                        float animatedValue = (float) valueAnimator.getAnimatedValue();
                        BarLenght = (float) (animatedValue * (getWidth() - BasePadding * 2) / 100);
                        Log.i(TAG, "setValues: valueAnimator:" + animatedValue);
                        Log.i(TAG, "setValues: BarLenght:" + BarLenght);

                        LableSorce = (int) animatedValue + "分";
                        postInvalidate();
                    }
                });
                animator.setDuration(3000);

            }
            animator.start();


        } else {
            BarLenght = (float) (values * (getWidth() - BasePadding * 2) / 100);
            LableSorce = (int) values + "分";

            postInvalidate();
        }
    }

    @Override
    public void onClick(View view) {
        setValues(100, true);

    }
}

一个类似支付宝 分数自定义控件

效果


zzzt.gif

代码

public class CirlcleBar extends View implements View.OnClickListener {

    Paint mRadarPaint;

    // 弧度的宽度
    int mBarWidth = 20;
    float TextHeight = 0;
    int BarBgColor = Color.WHITE;


    String sorce = "";
    String sorceLabel = "分";
    String defaultLabel = "上次刷牙得分";
    Paint mTextPaint;

    float currentDegress ;//当前角度
    float currentSorce ;//当前分数
    float maxDegress = 220f;
    int mRadius = 0;
    int DefaultDegress = 160;
    int mRadarMargin = dipToPx(getContext(), 3);


    int DefWidth = dipToPx(getContext(), 240);
    int DefHeight = dipToPx(getContext(), 120);


    Paint mBarBgPaint;
    Paint mBarPaint;
    private String TAG = getClass().getName();

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

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

    public CirlcleBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mAttr(context, attrs, defStyleAttr);
    }


    float SorceSize;
    float SorceLableSize;
    float DefaultLableSize;
    String DefaultLable = "上次刷牙得分";

    Paint mLittleCirlcePaint;
    int mLittleRadius;
    //获取属性
    private void mAttr(Context context, AttributeSet attrs, int defStyleAttr) {

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.UsmileCircleBar, defStyleAttr, 0);
        SorceSize = typedArray.getDimension(R.styleable.UsmileCircleBar_mSorceSize, 72);
        SorceLableSize = typedArray.getDimension(R.styleable.UsmileCircleBar_mSorceLableSize, 42);
        DefaultLableSize = typedArray.getDimension(R.styleable.UsmileCircleBar_DefaultLableSize, 42);
        DefaultLable = typedArray.getString(R.styleable.UsmileCircleBar_DefaultLabe);


    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        init();

    }


    private void init() {

        mRadarPaint = new Paint();
        mRadarPaint.setStyle(Paint.Style.FILL);
        mRadarPaint.setStrokeWidth(20);
        mRadarPaint.setAntiAlias(true);

        mBarBgPaint = new Paint();
        mBarBgPaint.setStyle(Paint.Style.STROKE);
        mBarBgPaint.setStrokeWidth(mBarWidth);
        mBarBgPaint.setStrokeCap(Paint.Cap.ROUND);
        mBarBgPaint.setColor(BarBgColor);
        mBarBgPaint.setAntiAlias(true);
        mBarBgPaint.setAlpha(50);

        mBarPaint = new Paint();
        mBarPaint.setColor(Color.BLUE);
        mBarPaint.setStyle(Paint.Style.STROKE);
        mBarPaint.setStrokeWidth(mBarWidth);
        mBarPaint.setAntiAlias(true);

        mBarPaint.setStrokeCap(Paint.Cap.ROUND);
        mTextPaint = new Paint();

        mLittleCirlcePaint=new Paint();
        mLittleCirlcePaint.setStyle(Paint.Style.FILL);
        setLayerType(View.LAYER_TYPE_SOFTWARE,mLittleCirlcePaint);

        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setAntiAlias(true);
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        TextHeight = (fontMetrics.bottom - fontMetrics.top) / 2;


        try {
/*            Uri uri=Uri.parse("android:resource://"+getContext().getPackageName()+"/"+R.font.alibaba_puhuiti_medium);
            mTextPaint.setTypeface(Typeface.createFromFile(uri.getPath()));*/

            mTextPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "font/alibaba_puhuiti_medium.otf"));
        } catch (Exception e) {
            e.printStackTrace();
        }


        //宽高 最短 的作为 直径
        mRadius = Math.min(getWidth() / 2, getHeight()/2);
        mLittleRadius= (int) (mRadius*0.5);
        setOnClickListener(this);

        //测试
        setValues(80, true);


    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int sizeWith = MeasureSpec.getSize(widthMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);

        //根据模式来 决定宽度
        switch (modeWidth) {

            case MeasureSpec.EXACTLY://match_parent  精确的度数
                DefWidth = sizeWith;
                break;
            case MeasureSpec.AT_MOST://wrap_content  适配的度数


                break;
        }


        //根据模式来 决定宽度
        switch (modeHeight) {

            case MeasureSpec.EXACTLY://match_parent  精确的度数
                DefHeight = sizeHeight;
                break;
            case MeasureSpec.AT_MOST://wrap_content  适配的度数


                break;
        }


        setMeasuredDimension(DefWidth, DefHeight);
    }

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

        drawBarBg(canvas);
        drawBar(canvas);
        drawRadar(canvas);
        drawLittelCirle(canvas);
        drawText(canvas);


    }


    private void drawLittelCirle(Canvas canvas) {



        canvas.save();
        canvas.translate(getWidth() / 2, getHeight()/2);
        mLittleCirlcePaint.setColor(Color.parseColor("#393948"));
        mLittleCirlcePaint.setMaskFilter(new BlurMaskFilter(mLittleRadius*0.1f, BlurMaskFilter.Blur.SOLID));

        canvas.drawCircle(0,0,mLittleRadius,mLittleCirlcePaint);

        mLittleCirlcePaint.setColor(Color.parseColor("#2F2F3A"));
        mLittleCirlcePaint.setMaskFilter(new BlurMaskFilter(mLittleRadius*0.1f, BlurMaskFilter.Blur.OUTER));
        canvas.drawCircle(0,0,mLittleRadius,mLittleCirlcePaint);
        canvas.restore();
    }


    //字体
    private void drawText(Canvas canvas) {
        canvas.save();
        canvas.translate(getWidth() / 2, getHeight()/2);

        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setTextSize(SorceSize);
        TextHeight = (mTextPaint.getFontMetrics().bottom - mTextPaint.getFontMetrics().top) / 2;

        sorce= ((int) currentSorce)+"";

        //分数
        mTextPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(),"font/alibaba_puhuiti_medium.otf"));
        mTextPaint.setAlpha(255);

        canvas.drawText(sorce, 0,  0, mTextPaint);
        //分标签
        float soreceStrWidth = mTextPaint.measureText(sorce);
        mTextPaint.setTextAlign(Paint.Align.LEFT);
        mTextPaint.setAlpha(201);
        mTextPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(),"font/alibaba_puhuiti_regular.otf"));
        mTextPaint.setTextSize(SorceLableSize);

        canvas.drawText(sorceLabel, soreceStrWidth / 2, 0, mTextPaint);
        //上次刷牙得分
        TextHeight = (mTextPaint.getFontMetrics().bottom - mTextPaint.getFontMetrics().top) / 2;
        mTextPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(),"font/alibaba_puhuiti_regular.otf"));
        mTextPaint.setAlpha(153);

        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setTextSize(DefaultLableSize);
        canvas.drawText(defaultLabel, 0, TextHeight*2, mTextPaint);
        canvas.restore();
    }


    //当前进度
    private void drawBar(Canvas canvas) {
        canvas.save();
        canvas.translate(getWidth() / 2, getHeight()/2);
        RectF mRectf = new RectF(-mRadius + mBarWidth / 2, -mRadius + mBarWidth / 2, mRadius - mBarWidth / 2, mRadius - mBarWidth / 2);
        mBarPaint.setShader(new LinearGradient(-mRadius+mBarWidth/2,0,mRadius-mBarWidth/2,0,new int[]{0xFFBC60C4,0xFF5C63FA},new float[]{0.3f,0.8f}, Shader.TileMode.CLAMP));
        canvas.drawArc(mRectf, DefaultDegress, currentDegress, false, mBarPaint);
        canvas.restore();
    }


    int BasePadding=dipToPx(getContext(),8);
    //弧度的背景色
    private void drawBarBg(Canvas canvas) {


        canvas.save();
        canvas.translate(getWidth() / 2, getHeight()/2);
        /*去掉进度条宽度*/
        RectF mRectf = new RectF(-mRadius + mBarWidth / 2, -mRadius + mBarWidth / 2, mRadius - mBarWidth / 2, mRadius - mBarWidth / 2);
        canvas.drawArc(mRectf, DefaultDegress, maxDegress, false, mBarBgPaint);
        canvas.restore();
    }


    /*雷达弧*/
    public void drawRadar(Canvas canvas) {

        canvas.save();
        canvas.translate(getWidth() / 2, getHeight()/2);

        //画扫描
        mRadarPaint.setShader(new SweepGradient(0, 0, new int[]{Color.TRANSPARENT, 0x555C63FA}, new float[]{0.95F, 0.99F}));

        canvas.rotate(DefaultDegress + currentDegress);
        RectF mRect = new RectF(-mRadius + mBarWidth + mRadarMargin, -mRadius + mBarWidth + mRadarMargin, mRadius - mBarWidth - mRadarMargin, mRadius - mBarWidth - mRadarMargin);
        canvas.drawArc(mRect, 0, 360, true, mRadarPaint);

        canvas.restore();
    }


    ValueAnimator mValueAnimator;
    int  mValues=0;
    public void setValues(final int values, boolean isAnm) {

        mValues=values;
        if (isAnm) {


            if (mValueAnimator != null) {
                mValueAnimator.cancel();
                mValueAnimator.setIntValues(0, values);
                mValueAnimator.start();
            } else {
                mValueAnimator = ValueAnimator.ofInt(0, values);
                mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {

                        int animatedValue = (int) animation.getAnimatedValue();
                        currentDegress = (maxDegress-DefaultDegress)*animatedValue/100;
                        currentSorce=animatedValue;
                        postInvalidate();

                    }
                });
                mValueAnimator.setDuration(3000);
                mValueAnimator.start();

            }
        } else {
            currentDegress = values;

            postInvalidate();

        }
    }

    @Override
    public void onClick(View v) {
        if (mValueAnimator.isRunning()) {
            return;
        } else {
            mValueAnimator.start();
        }
    }

    /**
     * dip 转换成px
     *
     * @param dip
     * @return
     */
    public static int dipToPx(Context context, float dip) {
        float density = context.getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
    }
}

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

推荐阅读更多精彩内容