自定义View之三-画笔(计步器效果)

2017-11-13  本文已影响0人  woochen123

效果图

step.gif

1.自定义属性

    <declare-styleable name="StepView">
        <attr name="maxStep" format="integer"></attr>
        <attr name="currentStep" format="integer"/>
        <attr name="stepColor" format="color|reference"/>
        <attr name="outColor" format="color|reference"/>
        <attr name="innerColor" format="color|reference"/>
        <attr name="stepSize" format="dimension"/>
        <attr name="roundWidth" format="float"/>
    </declare-styleable>

2.继承VIew


/**
 *@author woochen123
 *@time 2017/11/13 15:39
 *@desc
 */

public class StepView extends View {
    private static final String TAG = "StepView";
    //最大步数 默认1000
    private int mMaxStep = 100;
    //当前步数 默认500
    private int mCurrentStep = 50;
    //控件宽度
    private int mViewWidth;
    //空间高度
    private int mViewHeight;
    //圆环宽度
    private int mRoundWidth = 30;
    //起始角度
    private float mStartAngle = 135;
    //旋转角度
    private float mSweepAngle = 270;
    //步数文字大小 sp
    private int mTextSize = 15;
    //步数文字颜色
    private int mTextColor = Color.RED;
    //外层圆环颜色
    private int mOutColor = Color.BLUE;
    //内层圆环颜色
    private int mInnerColor = Color.RED;


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

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

    public StepView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //自定义属性
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.StepView);
        mMaxStep = array.getInt(R.styleable.StepView_maxStep, mMaxStep);
        mRoundWidth = (int) array.getFloat(R.styleable.StepView_roundWidth, mRoundWidth);
        mCurrentStep = array.getInt(R.styleable.StepView_currentStep, mCurrentStep);
        mTextColor = array.getColor(R.styleable.StepView_stepColor, mTextColor);
        mOutColor = array.getColor(R.styleable.StepView_outColor, mOutColor);
        mInnerColor = array.getColor(R.styleable.StepView_innerColor, mInnerColor);
        mTextSize = array.getDimensionPixelSize(R.styleable.StepView_stepSize, sp2Px(mTextSize));
        array.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mViewWidth = MeasureSpec.getSize(widthMeasureSpec);
        mViewHeight = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (heightMode == MeasureSpec.AT_MOST) {
            //如果是包裹内容
            mViewHeight = mViewWidth;
        }
        setMeasuredDimension(mViewWidth, mViewHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //1.画背景圆弧
        int centerX = mViewWidth / 2;
        int centerY = mViewHeight / 2;
        //半径
        int radius = centerX - mRoundWidth;
        //矩形区域
        RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
        Paint mPaint = new Paint();
        mPaint.setColor(mOutColor);
        //设置圆弧的宽度(设置空心线宽)
        mPaint.setStrokeWidth(mRoundWidth);
        //设置画笔的样式
        mPaint.setStyle(Paint.Style.STROKE);
        //当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的图形样式,如圆形样式 Cap.ROUND,或方形样式Cap.SQUARE
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        //设置结合处的形状,有三个选择:BEVEL、MITER、ROUND,分别表示直线、直角、圆角
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        //抗锯齿
        mPaint.setAntiAlias(true);
        //oval:圆弧所在的椭圆对象 startAngle:开始角度  水平向右是0°sweepAngle:旋转角度  useCenter:是否显示半径连线,true表示显示圆弧与圆心的半径连线,false表示不显示   panint:画笔
        canvas.drawArc(oval, mStartAngle, mSweepAngle, false, mPaint);

        //2.画进度圆弧
        mPaint.setColor(mInnerColor);
        float currentPercent = mCurrentStep * 1.0f / mMaxStep;
        canvas.drawArc(oval, mStartAngle, mSweepAngle * currentPercent, false, mPaint);

        //3.画步数文字
        //绘制文字
        String mStep = mCurrentStep + "";
        //重置画笔
        mPaint.reset();
        //无锯齿
        mPaint.setAntiAlias(true);
        //设置文字大小
        mPaint.setTextSize(mTextSize);
        //设置文字颜色
        mPaint.setColor(mTextColor);
        Log.e(TAG, "onDraw: "+mTextColor );
        //测量文字的宽高
        Rect textBounds = new Rect();
        mPaint.getTextBounds(mStep, 0, mStep.length(), textBounds);
        //计算文字的基线
        int dx = (getWidth() - textBounds.width()) / 2;
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        float baseLine = getHeight() / 2 + (fontMetrics.bottom - fontMetrics.top) / 2  - fontMetrics.bottom;
        //text:要绘制的内容 x:基线的横坐标 y:基线的纵坐标 paint:画笔
        canvas.drawText(mStep, dx, baseLine, mPaint);
    }

    private int sp2Px(int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, sp, getResources().getDisplayMetrics());
    }

    /**
     * 设置最大步数
     * @param maxStep
     */
    public void setMaxStep(int maxStep) {
        if(maxStep < 0 ){
         throw new IllegalArgumentException("max 不能小于0!");
        }
        this.mMaxStep = maxStep;
    }

    /**
     * 设置当前步数
     * @param currentStep
     */
    public void setCurrentStep(int currentStep) {
        if(currentStep < 0 ){
            throw new IllegalArgumentException("max 不能小于0!");
        }
        this.mCurrentStep = currentStep;
        invalidate();
    }
}

3.使用

    <com.example.admin.testapplication.views.step.StepView
        android:id="@+id/stepView"
        app:stepSize="50sp"
        app:stepColor="#00ff00"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
     final StepView stepView = (StepView) findViewById(R.id.stepView);
        stepView.setMaxStep(1000);
        ValueAnimator valueAnimator =ValueAnimator.ofInt(0,800);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
                stepView.setCurrentStep(value);
            }
        });
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.setDuration(1500);
        valueAnimator.start();
上一篇下一篇

猜你喜欢

热点阅读