美文网首页
自定义View之QQ运动记步

自定义View之QQ运动记步

作者: Noblel | 来源:发表于2017-12-14 11:54 被阅读0次

    作者:Noblel
    链接:http://www.jianshu.com/p/a21730618ca9
    请尊重原创,谢谢!

    需求来源

    来自某一版本的QQ的运动记步


    实现思路

    1.分析元素和效果:有两个不同色圆弧,一个为进度一个为背景
    一个步数字体

    2.确定自定义属性:背景色,进度色,圆弧大小,字体大小和颜色,其余自己可以再加。

    3.编写QQStepView

    • 获取自定义属性

        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.QQStepView);
        mOuterColor = array.getColor(R.styleable.QQStepView_outerColor, mOuterColor);
        mInnerColor = array.getColor(R.styleable.QQStepView_innerColor, mInnerColor);
        mBorderWidth = (int) array.getDimension(R.styleable.QQStepView_borderWidth, mBorderWidth);
        mStepTextSize = (int) array.getDimension(R.styleable.QQStepView_stepTextSize, mStepTextSize);
        mStepTextColor = array.getColor(R.styleable.QQStepView_stepTextColor, mStepTextColor);
        array.recycle();
      
    • 初始化画笔

        //外圆弧画笔
        mOutPaint = new Paint();
        //设置抗锯齿
        mOutPaint.setAntiAlias(true);
        //设置弧宽
        mOutPaint.setStrokeWidth(mBorderWidth);
        mOutPaint.setColor(mOuterColor);
        //设置画笔实心
        mOutPaint.setStyle(Paint.Style.STROKE); 
        //设置画笔线冒也就是弧的头样式
        mOutPaint.setStrokeCap(Paint.Cap.ROUND);
      
        //内圆弧画笔
        mInnerPaint = new Paint();
        mInnerPaint.setAntiAlias(true);
        mInnerPaint.setStrokeWidth(mBorderWidth);
        mInnerPaint.setColor(mInnerColor);
        mInnerPaint.setStyle(Paint.Style.STROKE);
        mInnerPaint.setStrokeCap(Paint.Cap.ROUND);
      
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(mStepTextColor);
        mTextPaint.setTextSize(mStepTextSize);
      
    • 画外圆弧

        //圆心,这里要注意我们的视图要保证为正方形。所以要在onMeasure中重写
        int center = getWidth() / 2;
        int radius = getWidth() / 2 - mBorderWidth / 2;
        mRectF.left = center - radius;
        mRectF.top = center - radius;
        mRectF.right = center + radius;
        mRectF.bottom = center + radius;
        //画弧,RectF和Rect的区别后面讲
        canvas.drawArc(mRectF, 135, 270, false, mOutPaint);
      
    • 画内圆弧

        //mCurrentStep为当前步数,mStepMax最大步数可以设置为属性也可以直接设置
        float sweepAngle = (float) mCurrentStep / mStepMax;
        canvas.drawArc(mRectF, 135, sweepAngle * 270, false, mInnerPaint);
      
    • 画文字

        //在自定义View之变色文字讲解过
        String str = mCurrentStep + "步";
        mTextPaint.getTextBounds(str, 0, str.length(), mTextBounds);
        int dx = center - mTextBounds.width() / 2;
        Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
        int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
        int baseLine = center + dy;
        canvas.drawText(str, dx, baseLine, mTextPaint);
      
    • 原理图


      原理图

    测试使用:

        final QQStepView qqStepView = findViewById(R.id.step_view);
        qqStepView.setStepMax(3000);
    
        //属性动画
        ValueAnimator animator = ObjectAnimator.ofFloat(0, 3000);
        animator.setInterpolator(new AccelerateInterpolator());
        animator.setDuration(3000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float currentStep = (float) animation.getAnimatedValue();
                qqStepView.setCurrentStep((int) currentStep);
            }
        });
        animator.start();
    

    RectF和Rect的区别

    Rect是“Rectangle”简写的英文单词,中文意思“矩形或长方形”,Rect对象持有一个矩形的四个int坐标值,RectF对象持有一个矩形的四个float坐标值,这是两者最大的区别。从实现的方式上看,Rect是一个final类实现Parcelable接口,RectF是一个普通类实现Parcelable接口,Rect和RectF除了记录的坐标数据类型不一样外,其他没什么太大差别。

    全部源码

    QQ运动记步源码

    相关文章

      网友评论

          本文标题:自定义View之QQ运动记步

          本文链接:https://www.haomeiwen.com/subject/mnohwxtx.html