Android自定义View实现仿QQ实现运动步数效果

Posted SiberiaDante

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android自定义View实现仿QQ实现运动步数效果相关的知识,希望对你有一定的参考价值。

效果图:

 

1、attrs.xml中

<declare-styleable name="QQStepView">
        <attr name="outerColor" format="color"/>
        <attr name="innerColor" format="color"/>
        <attr name="borderWidth" format="dimension"/>
        <attr name="stepViewTextSize" format="dimension"/>
        <attr name="stepViewTextColor" format="color"/>
    </declare-styleable>

2、QQStepView

public class QQStepView extends View {
    private int mOuterColor = Color.GRAY;
    private int mInnerColor = Color.RED;
    private float mBorderWidth = 20.0f;//20代表的20px
    private float mStepViewTextSize = 12.0f;
    private int mStepViewTextColor = Color.BLACK;
    private Paint mOutPaint;

    private int mStepMax;//最大的数值
    private int mCurrentStep;//当前的数值
    private Paint mInnerPaint;

    private Paint mTextPaint;


    public QQStepView(Context context) {
        this(context, null);

    }

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

    public QQStepView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //1分析效果
        //2确定自定义属性,编写attr.xml
        //3在布局中使用
        //4在自定义View中获取自定义属性
        //5onMeasure
        //6onDraw
        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 = array.getDimension(R.styleable.QQStepView_borderWidth, mBorderWidth);
        mStepViewTextColor = array.getColor(R.styleable.QQStepView_stepViewTextColor, mStepViewTextColor);
        mStepViewTextSize = array.getDimension(R.styleable.QQStepView_stepViewTextSize, mStepViewTextSize);
        array.recycle();
        //外层圆弧画笔
        mOutPaint = new Paint();
        mOutPaint.setAntiAlias(true);
        mOutPaint.setStrokeWidth(mBorderWidth);
        mOutPaint.setColor(mOuterColor);
        mOutPaint.setStrokeCap(Paint.Cap.ROUND);//两端变圆弧
//        mOutPaint.setStyle(Paint.Style.FILL);
        mOutPaint.setStyle(Paint.Style.STROKE);
        //内层圆弧画笔
        mInnerPaint = new Paint();
        mInnerPaint.setAntiAlias(true);
        mInnerPaint.setStrokeWidth(mBorderWidth);
        mInnerPaint.setColor(mInnerColor);
        mInnerPaint.setStrokeCap(Paint.Cap.ROUND);//两端变圆弧
//        mOutPaint.setStyle(Paint.Style.FILL);
        mInnerPaint.setStyle(Paint.Style.STROKE);
        //文字画笔
        mTextPaint = new Paint();
        mInnerPaint.setAntiAlias(true);
        mInnerPaint.setColor(mStepViewTextColor);
        mTextPaint.setTextSize(mStepViewTextSize);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //在布局文件中,可能wrap_content,可能高宽不一致
        //获取模式 AT_MOST
        //宽度高度不一致时取最小值,保持是个正方形
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(width > height ? height : width, width > height ? height : width);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画外圆弧:
//        int center = getWidth() / 2;
//        int radius= (int) (getWidth()/2-mBorderWidth/2);
//        RectF rectF = new RectF(center-radius, center-radius, center+radius, center+radius);
//        int radius = (int) (getWidth() / 2 - mBorderWidth / 2);
        RectF rectF = new RectF(mBorderWidth / 2, mBorderWidth / 2, getWidth() - mBorderWidth / 2,
                getWidth() - mBorderWidth / 2);
        canvas.drawArc(rectF, 135, 270, false, mOutPaint);
        //画内圆弧:百分比,由用户设置的
        if (mStepMax == 0) {
            return;//防止第一次进入时为0,引起错误
        }
        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;//文字的起始位置
        //基线
        Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
        int dy = (fontMetricsInt.bottom = fontMetricsInt.top) - fontMetricsInt.bottom;
        int baseLine = getHeight() / 2 + dy;
        canvas.drawText(stepText, dx, baseLine, mTextPaint);
    }

    //其他,动画效果等
    public synchronized void setStepMax(int stepMax) {
        this.mStepMax = stepMax;
    }

    //    synchronized,防止多线程操作出错
    public synchronized void setCurrentStep(int currentStep) {
        this.mCurrentStep = currentStep;
        //不断绘制
        invalidate();
    }
}

 

3、在Activity布局中

<com.siberiadante.view.QQStepView
        android:id="@+id/step_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        app:borderWidth="10dp"
        app:innerColor="@color/blue"
        app:outerColor="@color/colorAccent"
        app:stepViewTextColor="@color/blue"
        app:stepViewTextSize="28sp" />

4、在Activity中

 mTvStart = (TextView) findViewById(R.id.tv_start);
        stepView = (QQStepView) findViewById(R.id.step_view);
        stepView.setStepMax(10000);
//        stepView.setCurrentStep(5000);
        //属性动画
        final ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 9000);
        valueAnimator.setDuration(3000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float value = (float) valueAnimator.getAnimatedValue();
                stepView.setCurrentStep((int)value);
            }
        });
        mTvStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                valueAnimator.start();

            }
        });
    }

 

我的微信公众号:tstongxiao

github地址:https://github.com/SiberiaDante/SiberiaDanteLib/blob/master/siberiadante/src/main/java/com/siberiadante/view/QQStepView.java

 

参考文章:http://www.jianshu.com/p/4e0eb9bb09ab

 

以上是关于Android自定义View实现仿QQ实现运动步数效果的主要内容,如果未能解决你的问题,请参考以下文章

android 自定义View:仿QQ拖拽效果

android 自定义View:仿QQ拖拽效果

Android高级控件——自定义ListView高仿一个QQ可拖拽列表的实现

Android 中自定义View,实现小球往复运动

Android进阶之自定义View实战仿iOS UISwitch控件实现

Android进阶之自定义View实战仿iOS UISwitch控件实现