自定义View - 仿QQ运动步数进度效果

1.效果

2.创建QQStepView自定义View类
public class QQStepView extends View {
    public QQStepView(Context context) {
        this(context,null);
    }

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

    public QQStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}
3.在res/values创建attas.xml文件,编写自定义属性
    <!--自定义QQ运动步数-->
    <declare-styleable name="QQStepView">
        <attr name="outerColor" format="color"/>
        <attr name="innerColor" format="color"/>
        <attr name="borderWidth" format="dimension"/>
        <attr name="stepTextSize" format="dimension"/>
        <attr name="stepTextColor" format="color"/>
    </declare-styleable>
4.在布局文件中获取自定义View控件
        <com.itjs.myapplication.QQStepView
            android:layout_gravity="center"
            app:outerColor="#03A9F4"
            app:innerColor="#E91E63"
            app:borderWidth="6dp"
            app:stepTextColor="#E91E63"
            app:stepTextSize="16sp"
            android:layout_width="80dp"
            android:layout_height="80dp"/>
5.获取自定义属性
    private int mOuterColor = Color.RED;
    private int mInnerColor = Color.BLUE;
    private int mBorderWidth = 20;
    private int mStepTextSize;
    private int mStepTextColor;
    private Paint mOutPaint,mInnerPaint,mTextPaint;
    private int mStepMax = 100;
    private int mCurrentStep = 50;

    public QQStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        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 = 
        array.getDimensionPixelSize(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);
//        mPaint.setStyle(Paint.Style.FILL); //画笔实心
        mOutPaint.setStyle(Paint.Style.STROKE); //画笔空心
        mOutPaint.setStrokeCap(Paint.Cap.ROUND); //圆角

        mInnerPaint = new Paint();
        mInnerPaint.setAntiAlias(true); //抗锯齿
        mInnerPaint.setStrokeWidth(mBorderWidth);
        mInnerPaint.setColor(mInnerColor);
//        mPaint.setStyle(Paint.Style.FILL); //画笔实心
        mInnerPaint.setStyle(Paint.Style.STROKE); //画笔空心
        mInnerPaint.setStrokeCap(Paint.Cap.ROUND); //圆角

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true); //抗锯齿
        mTextPaint.setStrokeWidth(mBorderWidth);  //画笔宽度
        mTextPaint.setColor(mStepTextColor);
        mTextPaint.setTextSize(mStepTextSize);


    }
6.onMeasure()
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //在调用者布局文件中可能wrap_content
        //获取模式 AT_MOST 40dp
        //宽高不一致取最小值 确保是正方形
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(width>height?height:width,width>height?height:width);
    }
7.画外圆弧、内圆弧,文字
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int center = getWidth() /2;
        int radius = getWidth() /2 - mBorderWidth/2;
        //画外圆弧
        /**
         * 参数一:起点的Y轴坐标
         * 参数二:起点的X轴坐标
         * 参数三:终点的Y轴坐标
         * 参数四:终点的Y轴坐标
         */
        RectF rectF = new RectF(center-radius,center-radius
                ,center+radius,center+radius);
        canvas.drawArc(rectF,135,270,false, mOutPaint);
        if (mStepMax == 0) return;
//        画内圆弧
        float sweepAngle = (float) mCurrentStep/mStepMax;
        canvas.drawArc(rectF,135,sweepAngle*270,false, mInnerPaint);

        //画文字
        String stepText = mCurrentStep+"";
        Rect textBounds = new Rect();
        mTextPaint.getTextBounds(stepText,0,stepText.length(),textBounds);
        int dx = getWidth()/2-textBounds.width()/2;
        //基线 baseLine
        Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
        int dy = (fontMetrics.bottom - fontMetrics.top) - fontMetrics.bottom;
        int baseLine = getHeight()/2+dy;
        canvas.drawText(stepText,dx,baseLine,mTextPaint);
    }
8.动画加载 
    public void setStepMax(int stepMax) {
        this.mStepMax = stepMax;
    }

    public void setCurrentStep(int currentStep) {
        this.mCurrentStep = currentStep;

        //不断绘制
        invalidate();
    }
public class MainActivity extends AppCompatActivity {

    private QQStepView qqStepView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        qqStepView = findViewById(R.id.step_view);
        qqStepView.setStepMax(4000);
        //属性动画
        ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 3000);
        valueAnimator.setDuration(1000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animator) {
                float currentStep = (float) animator.getAnimatedValue();
                qqStepView.setCurrentStep((int) currentStep);
            }
        });
        valueAnimator.start();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值