自定义View--带百分比圆型进度条

2017-12-28  本文已影响0人  MinicupSimon

先上效果图

progressbar.gif

知识点

1. Canvas简单操作

2. 阴影效果的实现

3. 动画效果的实现

个人觉得,像这样比较简单的控件,并且使用场合不多的情况下,无须按照标准的自定义View的步骤来, 我指的是在attr.xml中定义并声明属性,然后再从控件中获取TypedArray。不光写起来麻烦,而且引用也麻烦
将下面代码直接Copy到项目中,AS会将包名也改掉,一步到位。再根据自己的需求,简单修改即可。
package com.minicup.custom.progressbar;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;


/**
 * Created by gy on 2017/12/27.
 */

public class CircleView extends View {

    /**
     * 中间圆及进度条颜色
     */
    private String mReachColor = "#54c484";

    /**
     * 默认外环背景颜色
     */
    private String mDefaultColor = "#dddddd";

    private Paint mCenterPaint;
    private Paint mRingPaint;
    private Paint mTextPaint;

    /**
     * ACTION_UP时的阴影
     */
    private BlurMaskFilter maskfilterUp;

    /**
     * ACTION_DOWN时的阴影
     */
    private BlurMaskFilter maskfilterDown;

    private RectF ringRect;
    /**
     * 外环宽度
     */
    private int mRingWidth = dp2px(10);
    /**
     * 阴影大小
     */
    private int mShadowRadius = dp2px(5);

    /**
     * 控件的大小
     */
    private int mViewRadius = dp2px(100);

    /**
     * 起使角度
     */
    private float startAngle = 0;

    /**
     * 终止角度
     */
    private float endAngle = 0;

    /**
     * 动画时,当前的角度
     */
    private float currentAngle;

    /**
     * 中央文字
     */
    private String mPercentage = "";

    /**
     * 字体大小
     */
    private int mTextSize = 30;
    private ValueAnimator anim;

    /**
     * 动画时,当前的百分比
     */
    private int p;

    public CircleView(Context context) {
        super(context, null);
    }

    public CircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        setLayerType(LAYER_TYPE_SOFTWARE, null);

        mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        maskfilterUp = new BlurMaskFilter(mShadowRadius, BlurMaskFilter.Blur.SOLID);
        maskfilterDown = new BlurMaskFilter(mShadowRadius*2, BlurMaskFilter.Blur.SOLID);
        mCenterPaint.setMaskFilter(maskfilterUp);
        mCenterPaint.setColor(Color.parseColor(mReachColor));

        mRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRingPaint.setColor(Color.parseColor(mDefaultColor));
        mRingPaint.setStrokeCap(Paint.Cap.ROUND);
        mRingPaint.setStrokeWidth(mRingWidth);
        mRingPaint.setStyle(Paint.Style.STROKE);

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setTextSize(spTopx(mTextSize));
        mTextPaint.setTypeface(Typeface.SANS_SERIF);

        //这里应该在Activity中设置
        setPercentage(70);
    }



    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        ringRect = new RectF(mRingWidth/2, mRingWidth/2, w-mRingWidth/2, w-mRingWidth/2);
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(mViewRadius*2, mViewRadius*2);
    }


    @Override
    protected void onDraw(Canvas canvas) {

        int radius = mViewRadius;
        //中央圆
        canvas.drawCircle(radius, radius, radius * 0.8f, mCenterPaint);

        //外环背景
        mRingPaint.setColor(Color.parseColor(mDefaultColor));
        canvas.drawCircle(radius, radius, radius-mRingWidth/2, mRingPaint);
        //外环进度
        mRingPaint.setColor(Color.parseColor(mReachColor));
        canvas.drawArc(ringRect, startAngle, currentAngle, false, mRingPaint);

        //中央文字
        Rect rect = new Rect();
        mTextPaint.getTextBounds(mPercentage, 0, mPercentage.length(), rect);
        canvas.drawText(mPercentage, 0, mPercentage.length(), radius-rect.width()/2, radius+rect.height()/2, mTextPaint);

        super.onDraw(canvas);
    }

    public int dp2px(int dp){
        return ((int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics()) + 0.5));
    }

    private float spTopx(int sp) {
        return ((int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics()) + 0.5));

    }


    /**
     * 用以实现点击效果
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int actionMasked = event.getActionMasked();
        if(actionMasked==MotionEvent.ACTION_DOWN){
            mCenterPaint.setMaskFilter(maskfilterDown);
            startAnimation();
            postInvalidate();
        }else if(actionMasked==MotionEvent.ACTION_UP){
            mCenterPaint.setMaskFilter(maskfilterUp);
            postInvalidate();
        }
        return true;
    }


    public void setPercentage(int p) {
        endAngle = 360 * p / 100;
        this.p = p;
        mPercentage = String.format("%s%%", p);
        startAnimation();
    }


    public void startAnimation(){
        anim = ValueAnimator.ofFloat(startAngle, endAngle);
        anim.setInterpolator(new DecelerateInterpolator(1.1f));
        anim.setDuration(1000);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentAngle = (Float) animation.getAnimatedValue();
                mPercentage = String.format("%s%%", ((int) (p * currentAngle / endAngle)));
                postInvalidate();
            }
        });
        anim.start();
    }
}

上一篇下一篇

猜你喜欢

热点阅读