Android仿qq健康效果

最近又搞医疗项目,为了搞的高大上一天,仿照最近流行的qq健康的,干才开始自己写了一个用图片做为背景的,感觉太lou了,然后看大神写的,先看看效果吧,最好还是用自定义一个view控件
这里写图片描述

代码如下

package view;

import java.util.logging.Logger;

import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.example.demo11test.R;

public class QQHealthView  extends View {
     private static String TAG = "QQHealthView";

        private int mWidth;//自定义View宽
        private int mHeight;//自定义View高
        private int mBackgroundCorner;//背景四角的弧度

        private int mArcCenterX;
        private int mArcCenterY;
        private RectF mArcRect;

        private Paint mBackgroundPaint;
        private Paint mArcPaint;//最上面弧线的画笔
        private Paint mTextPaint;
        private Paint mDashLinePaint;//虚线的画笔
        private Paint mBarPaint;//竖条的画笔

        private int[] mSteps;
        private float mRatio;

        private Context mContext;

        private int mDefaultThemeColor;//主题色
        private int mDefaultUpBackgroundColor;//上层默认的背景色

        private int mThemeColor;
        private int mUpBackgroundColor;
        private float mArcWidth;
        private float mBarWidth;
        private int mMaxStep;
        private int mAverageStep;
        private int mTotalSteps;

        private int step = 25;
        private float percent = 0.5f;

        private Paint mAvatarPaint;

        public QQHealthView(Context context) {
            this(context, null);
        }

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

        public QQHealthView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            init();
        }

        private void init() {
            //下面这句是关闭硬件加速,防止某些4.0的设备虚线显示为实线的问题
            //可以在AndroidManifest.xml时的Application标签加上android:hardwareAccelerated=”false”,
            // 这样整件应用都关闭了硬件加速,虚线可以正常显示,但是,关闭硬件加速对性能有些影响,
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            //自定义View的宽高比例
            mRatio = 450.f / 525.f;
            //初始化一些默认的参数
            mBackgroundCorner = DensityUtils.dp2px(mContext, 5);
            mDefaultThemeColor = Color.parseColor("#2EC3FD");
            mDefaultUpBackgroundColor = Color.WHITE;
            mThemeColor = mDefaultThemeColor;
            mUpBackgroundColor = mDefaultUpBackgroundColor;
            mSteps = new int[]{10050, 15280, 8900, 9200, 6500, 5660, 9450};
            calculateSteps();
            //背景画笔
            mBackgroundPaint = new Paint();
            mBackgroundPaint.setAntiAlias(true);
            mBackgroundPaint.setColor(mThemeColor);
            //圆弧的画笔
            mArcPaint = new Paint();
            mArcPaint.setColor(mThemeColor);//画笔颜色
            mArcPaint.setAntiAlias(true);//抗锯齿
            mArcPaint.setStyle(Paint.Style.STROKE);//空心
            mArcPaint.setDither(true);//防抖动
            mArcPaint.setStrokeJoin(Paint.Join.ROUND);//在画笔的连接处是圆滑的
            mArcPaint.setStrokeCap(Paint.Cap.ROUND);//在画笔的起始处是圆滑的
            mArcPaint.setPathEffect(new CornerPathEffect(10));//画笔效果
            //文字画笔
            mTextPaint = new Paint();
            mTextPaint.setAntiAlias(true);
            //虚线画笔
            mDashLinePaint = new Paint();
            mDashLinePaint.setAntiAlias(true);
            mDashLinePaint.setColor(Color.parseColor("#C1C1C1"));
            mDashLinePaint.setStyle(Paint.Style.STROKE);
            mDashLinePaint.setPathEffect(new DashPathEffect(new float[]{8, 4}, 0));//画虚线
            //竖条画笔
            mBarPaint = new Paint();
            mBarPaint.setColor(mThemeColor);
            mBarPaint.setAntiAlias(true);
            mBarPaint.setStrokeCap(Paint.Cap.ROUND);
            //头像画笔
            mAvatarPaint = new Paint();
            mAvatarPaint.setAntiAlias(true);

            //加入动画
            AnimatorSet animatorSet = new AnimatorSet();

            //步数的动画
            ValueAnimator stepAnimator = ValueAnimator.ofInt(0, mSteps[mSteps.length - 1]);
            stepAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    step = (int) animation.getAnimatedValue();
                    invalidate();
                }
            });
//          stepAnimator.setDuration(1000);
//          stepAnimator.start();

            //圆环动画
            ValueAnimator percentAnimator = ValueAnimator.ofFloat(0, 1);
            percentAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    percent = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            // percentAnimator.setDuration(1000);
            // percentAnimator.start();
            animatorSet.setDuration(1000);
            animatorSet.playTogether(stepAnimator, percentAnimator);
            animatorSet.start();


        }

        public void setThemeColor(int color) {
            mThemeColor = color;
            mBackgroundPaint.setColor(mThemeColor);
            mArcPaint.setColor(mThemeColor);
            mBarPaint.setColor(mThemeColor);
            invalidate();
        }

        public void setSteps(int[] steps) {
            if (steps == null || steps.length == 0) throw new IllegalArgumentException("非法参数");
            mSteps = steps;
            calculateSteps();
            invalidate();

        }

        //将原始图片转化为圆形图片
        public Bitmap toRoundBitmap(Bitmap bitmap) {
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            int r;
            if (width > height) {
                r = height;
            } else {
                r = width;
            }
            Bitmap backgroundBmp = Bitmap.createBitmap(width,
                    height, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(backgroundBmp);
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            RectF rect = new RectF(0, 0, r, r);
            BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,
                    Shader.TileMode.CLAMP);
            paint.setShader(shader);
            canvas.drawRoundRect(rect, r / 2, r / 2, paint);
            return backgroundBmp;
        }

        //计算步数
        private void calculateSteps() {
            mTotalSteps = 0;
            mMaxStep = 0;
            mAverageStep = 0;
            for (int i = 0; i < mSteps.length; i++) {
                mTotalSteps += mSteps[i];
                if (mMaxStep < mSteps[i]) mMaxStep = mSteps[i];

            }
            mAverageStep = (int) (mTotalSteps * 1.f / mSteps.length);
        }

        //绘制最下层背景
        private void drawBelowBackground(int left, int top, int right, int bottom, int radius, Canvas canvas, Paint paint) {
            Path path = new Path();

            path.moveTo(left, top);

            path.lineTo(right - radius, top);
            path.quadTo(right, top, right, top + radius);

            path.lineTo(right, bottom - radius);
            path.quadTo(right, bottom, right - radius, bottom);

            path.lineTo(left + radius, bottom);
            path.quadTo(left, bottom, left, bottom - radius);

            path.lineTo(left, top + radius);
            path.quadTo(left, top, left + radius, top);

            canvas.drawPath(path, paint);
        }

        //绘制上层背景
        private void drawUpBackground(int left, int top, int right, int bottom, int radius, Canvas canvas, Paint paint) {
            Path path = new Path();

            path.moveTo(left, top);

            path.lineTo(right - radius, top);
            path.quadTo(right, top, right, top + radius);

            path.lineTo(right, bottom);

            path.lineTo(left, bottom);

            path.lineTo(left, top + radius);
            path.quadTo(left, top, left + radius, top);

            canvas.drawPath(path, paint);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int defaultWidth = Integer.MAX_VALUE;
            int width;
            int height;
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            //  int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            //  int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            if (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST) {
                width = widthSize;
            } else {
                width = defaultWidth;
            }
            int defaultHeight = (int) (width * 1.f / mRatio);
            height = defaultHeight;
            setMeasuredDimension(width, height);
            Log.i(TAG, "width:" + width + "| height:" + height);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mWidth = w;
            mHeight = h;

            mArcCenterX = (int) (mWidth / 2.f);
            mArcCenterY = (int) (160.f / 525.f * mHeight);
            mArcRect = new RectF();
            mArcRect.left = mArcCenterX - 125.f / 450.f * mWidth;
            mArcRect.top = mArcCenterY - 125.f / 525.f * mHeight;
            mArcRect.right = mArcCenterX + 125.f / 450.f * mWidth;
            mArcRect.bottom = mArcCenterY + 125.f / 525.f * mHeight;

            mArcWidth = 20.f / 450.f * mWidth;
            mBarWidth = 16.f / 450.f * mWidth;

            //画笔的宽度一定要在这里设置才能自适应
            mArcPaint.setStrokeWidth(mArcWidth);
            mBarPaint.setStrokeWidth(mBarWidth);
        }

        @SuppressLint("DrawAllocation")
        @Override
        protected void onDraw(Canvas canvas) {
            float startX;
            float startY;
            float stopX;
            float stopY;
            float xPos;
            float yPos;
            //1.绘制最下层背景
            mBackgroundPaint.setColor(mThemeColor);
            drawBelowBackground(0, 0, mWidth, mHeight, mBackgroundCorner, canvas, mBackgroundPaint);
            //2.绘制上面的背景
            mBackgroundPaint.setColor(mUpBackgroundColor);
            drawUpBackground(0, 0, mWidth, mWidth, mBackgroundCorner, canvas, mBackgroundPaint);
            //3.绘制圆弧
            canvas.drawArc(mArcRect, 120, 300 * percent, false, mArcPaint);
            //4.绘制圆弧里面的文字
            xPos = mArcCenterX;
            yPos = (int) (mArcCenterY - 40.f / 525.f * mHeight);
            mTextPaint.setTextAlign(Paint.Align.CENTER);
            mTextPaint.setTextSize(15.f / 450.f * mWidth);
            mTextPaint.setColor(Color.parseColor("#C1C1C1"));
            canvas.drawText("截至22:50分已走", xPos, yPos, mTextPaint);
            mTextPaint.setTextAlign(Paint.Align.CENTER);
            mTextPaint.setTextSize(42.f / 450.f * mWidth);
            mTextPaint.setColor(mThemeColor);
            canvas.drawText(step + "", mArcCenterX, mArcCenterY, mTextPaint);
            yPos = (int) (mArcCenterY + 50.f / 525.f * mHeight);
            mTextPaint.setColor(Color.parseColor("#C1C1C1"));
            mTextPaint.setTextSize(13.f / 450.f * mWidth);
            canvas.drawText("好友平均5620步", mArcCenterX, yPos, mTextPaint);
            xPos = (int) (mArcCenterX - 35.f / 450.f * mWidth);
            yPos = (int) (mArcCenterY + 120.f / 525.f * mHeight);
            canvas.drawText("第", xPos, yPos, mTextPaint);
            xPos = (int) (mArcCenterX + 35.f / 450.f * mWidth);
            canvas.drawText("名", xPos, yPos, mTextPaint);
            mTextPaint.setColor(mThemeColor);
            mTextPaint.setTextSize(24.f / 450.f * mWidth);
            canvas.drawText("10", mArcCenterX, yPos, mTextPaint);
            //5.绘制圆弧下面的文字
            xPos = (int) (25.f / 450.f * mWidth);
            yPos = (int) (330.f / 525.f * mHeight);
            mTextPaint.setTextAlign(Paint.Align.LEFT);
            mTextPaint.setColor(Color.parseColor("#C1C1C1"));
            mTextPaint.setTextSize(12.f / 450.f * mWidth);
            canvas.drawText("最近7天", xPos, yPos, mTextPaint);
            xPos = (int) ((450.f - 25.f) / 450.f * mWidth);
            yPos = (int) (330.f / 525.f * mHeight);
            mTextPaint.setTextAlign(Paint.Align.RIGHT);
            mTextPaint.setColor(Color.parseColor("#C1C1C1"));
            mTextPaint.setTextSize(12.f / 450.f * mWidth);
            canvas.drawText("平均" + mAverageStep + "步/天", xPos, yPos, mTextPaint);
            //6.画虚线
            xPos = (int) (25.f / 450.f * mWidth);
            yPos = (int) (352.f / 525.f * mHeight);
            stopX = xPos + (450.f - 50.f) / 450.f * mWidth;
            stopY = yPos;
            canvas.drawLine(xPos, yPos, stopX, stopY, mDashLinePaint);
            //7.绘制下面的竖条
            mTextPaint.setTextAlign(Paint.Align.CENTER);
            mTextPaint.setTextSize(10.f / 450.f * mWidth);
            startY = 388.f / 525.f * mHeight;

            for (int i = 0; i < mSteps.length; i++) {
                float barHeight = mSteps[i] * 1.f / mAverageStep * 35.f / 525.f * mHeight;
                startX = 55.f / 450.f * mWidth + i * (57.f / 450.f * mWidth);
                stopX = startX;
                stopY = startY - barHeight;
                if (mSteps[i] < mAverageStep) mBarPaint.setColor(Color.parseColor("#C1C1C1"));
                else mBarPaint.setColor(mThemeColor);
                canvas.drawLine(startX, startY, stopX, stopY, mBarPaint);
                canvas.drawText("0" + (i + 1) + "日", startX, startY + 25.f / 525.f * mHeight, mTextPaint);
            }
            //8.绘制蓝色层的文字以及头像
            yPos = (mHeight - mWidth) / 2.f + mWidth + 20.f / 450.f * mWidth / 2;
            xPos = 80.f / 450.f * mWidth;
            mTextPaint.setColor(Color.WHITE);
            mTextPaint.setTextSize(20.f / 450.f * mWidth);
            mTextPaint.setTextAlign(Paint.Align.LEFT);

            canvas.drawText("double江获得今日冠军", xPos, yPos, mTextPaint);

            Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.avastar);
            Rect dst = new Rect();//头像绘制到的矩形
            int rectWidth = (int) (30.f / 525.f * mHeight);//矩形的宽度
            dst.top = (int) ((mHeight - mWidth) / 2.f + mWidth - rectWidth / 2.f);
            dst.left = (int) (xPos - 40.f / 450 * mWidth);
            dst.bottom = (int) ((mHeight - mWidth) / 2.f + mWidth + rectWidth / 2.f);
            dst.right = (int) (xPos - 10.f / 450 * mWidth);
            bitmap = toRoundBitmap(bitmap);
            canvas.drawBitmap(bitmap, null, dst, mAvatarPaint);//绘制头像

            xPos = 425.f / 450.f * mWidth;
            mTextPaint.setTextAlign(Paint.Align.RIGHT);
            mTextPaint.setTextSize(15.f / 450.f * mWidth);
            canvas.drawText("查看 >", xPos, yPos, mTextPaint);
        }

        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouchEvent(MotionEvent event) {

            RectF rectF = new RectF();
            rectF.top = mWidth;
            rectF.left = 380.f / 450.f * mWidth;
            rectF.right = mWidth;
            rectF.bottom = mHeight;
            if (rectF.contains(event.getX(), event.getY())) {//当前点击的坐标在右下角的范围内
                //在这里可以做点击事件的监听
              Toast.makeText(mContext, "带开发", Toast.LENGTH_LONG).show();
                return false;
            } else {
                return super.onTouchEvent(event);
            }
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值