zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    STM32 F4 DAC DMA Waveform Generator
    STM32 F4 General-purpose Timers for Periodic Interrupts
    Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式
    Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
    查看SQL Server服务运行帐户和SQL Server的所有注册表项
    Pycharm使用技巧(转载)
    SQL Server 2014内存优化表的使用场景
    Python第十天 print >> f,和fd.write()的区别 stdout的buffer 标准输入 标准输出 从控制台重定向到文件 标准错误 重定向 输出流和输入流 捕获sys.exit()调用 optparse argparse
    Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
    Python第六天 类型转换
  • 原文地址:https://www.cnblogs.com/shen-hua/p/7238318.html
Copyright © 2011-2022 走看看