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

  • 相关阅读:
    企业远程视频会议云服务EasyRTC-SFU版本支持 https 功能设计逻辑
    企业视频远程办公会议通话系统EasyRTC在Windows2012部署运行出现“计算机中丢失VCRUNTIME140.dll”如何解决?
    IP摄像头RTSP协议客户端EasyNVR视频平台提示加密机授权异常原因分析
    【方案搭建】多个工程如何做监控视频的集中管控?EasyNVR视频平台打造智慧工厂新方向
    IP摄像头RTSP协议客户端EasyNVR视频平台如何调用主码流和子码流?
    如何通过私有化部署自建一套基于RTSP协议的视频流媒体边缘计算系统EasyNVR视频平台来实现网络摄像头的实时直播回看?
    IP网络摄像机RTMP协议互联网直播/点播平台EasyDSS直播间录像录制机制说明
    视频上云网关/网络穿透设备EasyNTS下载表格时后端打印报错信息,但是又不影响下载的问题如何解决
    视频高速上云网关EasyNTS组网服务2.1.1新版本无法兼容低版数据库问题解析
    视频上云/网络穿透/网络映射服务EasyNTS前端组织添加页面出现Vue冲突怎么解决?
  • 原文地址:https://www.cnblogs.com/shen-hua/p/7238318.html
Copyright © 2011-2022 走看看