image

前言

灵感来自几天前看到一位作者的仿芝麻信用自定义View的文章很不错,所以我换了一种方式来进行实现,写了旧版和新版芝麻信用分仪表盘的效果。

截图

这是我做的效果,还是有点差距的,嘿嘿。

image

image

正文

芝麻信用分的实现

首先初始化各种画笔,默认的size,padding,小圆点.

(因为实在找不到原版芝麻信用的带点模糊效果的小圆点,所以只好用这个代替)

//View的默认大小defaultSize = dp2px(250);//默认Padding大小arcDistance = dp2px(14);//外层圆环画笔mMiddleArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mMiddleArcPaint.setStrokeWidth(8);mMiddleArcPaint.setColor(Color.WHITE);mMiddleArcPaint.setStyle(Paint.Style.STROKE);mMiddleArcPaint.setAlpha(80);//内层圆环画笔mInnerArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mInnerArcPaint.setStrokeWidth(30);mInnerArcPaint.setColor(Color.WHITE);mInnerArcPaint.setAlpha(80);mInnerArcPaint.setStyle(Paint.Style.STROKE);//正中间字体画笔mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mTextPaint.setColor(Color.WHITE);mTextPaint.setTextAlign(Paint.Align.CENTER);//圆环大刻度画笔mCalibrationPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mCalibrationPaint.setStrokeWidth(4);mCalibrationPaint.setStyle(Paint.Style.STROKE);mCalibrationPaint.setColor(Color.WHITE);mCalibrationPaint.setAlpha(120);//圆环小刻度画笔mSmallCalibrationPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mSmallCalibrationPaint.setStrokeWidth(1);mSmallCalibrationPaint.setStyle(Paint.Style.STROKE);mSmallCalibrationPaint.setColor(Color.WHITE);mSmallCalibrationPaint.setAlpha(130);//圆环刻度文本画笔mCalibrationTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mCalibrationTextPaint.setTextSize(30);mCalibrationTextPaint.setColor(Color.WHITE);//外层进度画笔mArcProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mArcProgressPaint.setStrokeWidth(8);mArcProgressPaint.setColor(Color.WHITE);mArcProgressPaint.setStyle(Paint.Style.STROKE);mArcProgressPaint.setStrokeCap(Paint.Cap.ROUND);//外层圆环上小圆点Bitmap画笔mBitmapPaint = new Paint();mBitmapPaint.setStyle(Paint.Style.FILL);mBitmapPaint.setAntiAlias(true);//初始化小圆点图片bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_circle);//当前点的实际位置pos = new float[2];//当前点的tangent值tan = new float[2];matrix = new Matrix();

代码很简单,就是各种初始化,往下看.

View的测量,主要在给设置warp_content时候给定一个默认宽高值.

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ setMeasuredDimension(resolveMeasure(widthMeasureSpec, defaultSize), resolveMeasure(heightMeasureSpec, defaultSize));}//根据传入的值进行测量public int resolveMeasure(int measureSpec, int defaultSize){ int result = 0; int specSize = MeasureSpec.getSize(measureSpec); switch (MeasureSpec.getMode(measureSpec)) { case MeasureSpec.UNSPECIFIED: result = defaultSize; break; case MeasureSpec.AT_MOST: //设置warp_content时设置默认值 result = Math.min(specSize, defaultSize); break; case MeasureSpec.EXACTLY: //设置math_parent 和设置了固定宽高值 break; default: result = defaultSize; } return result;}

然后确定View的宽高后的回调方法.

@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh){ super.onSizeChanged(w, h, oldw, oldh); width = w; height = h; radius = width / 2; //外层圆环矩形 mMiddleRect = new RectF(defaultPadding, defaultPadding,width - defaultPadding, height - defaultPadding); //内层圆环矩形 mInnerRect = new RectF(defaultPadding + arcDistance, defaultPadding + arcDistance,width - defaultPadding - arcDistance, height - defaultPadding - arcDistance); // 外层进度矩形 mMiddleProgressRect = new RectF(defaultPadding, defaultPadding,width - defaultPadding, height - defaultPadding);}

这里就是初始化圆弧所需要的矩形实现,下边开始进行重点,绘制,

绘制外层的圆弧,很简单, 圆弧的起始角度,角度.

private void drawMiddleArc(Canvas canvas){ canvas.drawArc(mMiddleRect, mStartAngle, mEndAngle, false, mMiddleArcPaint);}

绘制内层圆弧

private void drawInnerArc(Canvas canvas){ canvas.drawArc(mInnerRect, mStartAngle, mEndAngle, false, mInnerArcPaint);}

绘制内层圆弧上的小刻度,画布旋转到圆弧左下角起点,计算出每条刻度线的起始点后,整个圆弧是210度,

每6角度绘制一条刻度线.

private void drawSmallCalibration(Canvas canvas){ //旋转画布 canvas.save(); canvas.rotate(-105, radius, radius); //计算刻度线的起点结束点 int startDst = (int) (defaultPadding + arcDistance - mInnerArcPaint.getStrokeWidth() / 2 - 1); int endDst = (int) (startDst + mInnerArcPaint.getStrokeWidth()); for (int i = 0; i <= 35; i++) { //每旋转6度绘制一个小刻度 canvas.drawLine(radius, startDst, radius, endDst, mSmallCalibrationPaint); canvas.rotate(6, radius, radius); } canvas.restore();}

绘制内层圆弧上的大刻度,350, 550, 600,650, 700, 950,对应的信用分值,

一样旋转画布,计算刻度线的起始点,计算出每次旋转的角度,每35度旋转一次,依次绘制对应的大刻度线,

然后绘制对应的文本内容,使用paint的measureText方法测量出文本的长度,依次绘制对应的文本内容.

private void drawCalibrationAndText(Canvas canvas){ //旋转画布进行绘制对应的刻度 canvas.save(); canvas.rotate(-105, radius, radius); //计算刻度线的起点结束点 int startDst = (int) (defaultPadding + arcDistance - mInnerArcPaint.getStrokeWidth() / 2 - 1); int endDst = (int) (startDst + mInnerArcPaint.getStrokeWidth()); //刻度旋转的角度 int rotateAngle = 210 / 10; for (int i = 1; i < 12; i++) { if (i % 2 != 0) { canvas.drawLine(radius, startDst, radius, endDst, mCalibrationPaint); } // 测量文本的长度 float textLen = mCalibrationTextPaint.measureText(sesameStr[i - 1]); canvas.drawText(sesameStr[i - 1], radius - textLen / 2, endDst + 40, mCalibrationTextPaint); canvas.rotate(rotateAngle, radius, radius); } canvas.restore();}

绘制中间的信用分值,信用等级,评估时间等文本,这个比较简单,直接drawText,依次高低排列绘制即可.

private void drawCenterText(Canvas canvas){ //绘制Logo mTextPaint.setTextSize(30); canvas.drawText("BETA", radius, radius - 130, mTextPaint); //绘制信用分数 mTextPaint.setTextSize(200); mTextPaint.setStyle(Paint.Style.STROKE); canvas.drawText(String.valueOf(mMinNum), radius, radius + 70, mTextPaint); //绘制信用级别 mTextPaint.setTextSize(80); canvas.drawText(sesameLevel, radius, radius + 160, mTextPaint); //绘制评估时间 mTextPaint.setTextSize(30); canvas.drawText(evaluationTime, radius, radius + 205, mTextPaint);}

绘制最外层的进度,这里使用的Path添加要绘制的圆弧,因为需要去不断的计算坐标点,主要用到了PathMeasure这个类,将绘制的圆弧加入到path中,

当前点的实际位置

private float[] pos;

当前的tangent值

private float[] tan;

获取路径的终点的正切值和坐标,然后根据坐标点绘制小圆点

PathMeasure pathMeasure = new PathMeasure(path, false);

pathMeasure.getPosTan(pathMeasure.getLength() * 1, pos, tan);

关于PathMeasure,推荐看AndroidNote,我也是跟着这个笔记学习的自定义控件.

private void drawRingProgress(Canvas canvas){ Path path = new Path(); path.addArc(mMiddleProgressRect, mStartAngle, mCurrentAngle); PathMeasure pathMeasure = new PathMeasure(path, false); pathMeasure.getPosTan(pathMeasure.getLength() * 1, pos, tan); matrix.reset(); matrix.postTranslate(pos[0] - bitmap.getWidth() / 2, pos[1] - bitmap.getHeight() / 2); canvas.drawPath(path, mArcProgressPaint); //起始角度不为0时候才进行绘制小圆点 if (mCurrentAngle == 0) return; canvas.drawBitmap(bitmap, matrix, mBitmapPaint); mBitmapPaint.setColor(Color.WHITE); canvas.drawCircle(pos[0], pos[1], 8, mBitmapPaint);}

好了,到这里所有绘制完毕了,接下来让圆弧进度条动起来吧,使用ValueAnimator,

进度条动画定义了圆弧进度条的开始角度mCurrentAngle,圆弧角度mTotalAngle,

数值动画定义了初始化minNum=0,maxNum根据传入的数值进行计算.

public void startAnim(){ ValueAnimator mAngleAnim = ValueAnimator.ofFloat(mCurrentAngle, mTotalAngle); mAngleAnim.setInterpolator(new AccelerateDecelerateInterpolator()); mAngleAnim.setDuration(3000); mAngleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){ @Override public void onAnimationUpdate(ValueAnimator valueAnimator){ mCurrentAngle = (float) valueAnimator.getAnimatedValue(); postInvalidate(); } }); mAngleAnim.start(); ValueAnimator mNumAnim = ValueAnimator.ofInt(mMinNum, mMaxNum); mNumAnim.setDuration(3000); mNumAnim.setInterpolator(new LinearInterpolator()); mNumAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator){ mMinNum = (int) valueAnimator.getAnimatedValue(); postInvalidate(); } }); mNumAnim.start();}

最后根据传入的信用分值计算圆弧进度条所到的角度.

public void setSesameValues(int values){ if (values <= 350){ mMaxNum = values; mTotalAngle = 0f; sesameLevel = "信用较差"; evaluationTime = "评估时间:" + getCurrentTime(); } else if (values <= 550){ mMaxNum = values; mTotalAngle = (values - 350) * 80 / 400f + 2; sesameLevel = "信用较差"; evaluationTime = "评估时间:" + getCurrentTime(); } else if (values <= 700) { mMaxNum = values; if (values > 550 && values <= 600){ sesameLevel = "信用中等"; } else if (values > 600 && values <= 650){ sesameLevel = "信用良好"; } else { sesameLevel = "信用优秀"; } mTotalAngle = (values - 550) * 120 / 150f + 43; evaluationTime = "评估时间:" + getCurrentTime(); } else if (values <= 950){ mMaxNum = values; mTotalAngle = (values - 700) * 40 / 250f + 170; sesameLevel = "信用极好"; evaluationTime = "评估时间:" + getCurrentTime(); } else{ mTotalAngle = 240f; } startAnim();}

最后

这篇文章只分析了新版的实现过程,旧版的的实现思路也差不多,代码也不复杂,可以直接看源码实现,由于本人文章写的不多,所以感觉把代码的实现用语言来组织还真挺难的,所以写的不好的地方还请各位大大见谅,有问题可联系我,最后希望如果觉得还可以的,请给个star, 谢谢啦.

Android 仿芝麻信用进度条,自定义View仿支付宝芝麻信用分仪表盘效果相关推荐

  1. android记账本折线图_Android自定义View - 仿支付宝月账单折线图

    前言 支付宝有个查看月账单的功能,最近一直在学习自定义View,于是就尝试着自己实现了一个类似的折线图. 下面是支付宝消费分析功能截图和自己实现的折线效果截图: 支付宝消费分析折线图.jpg 效果1. ...

  2. 自定义View实现支付宝芝麻信用页面功能

    此篇文章布局有些问题,调整后的请看这篇:http://blog.csdn.net/anny_lin/article/details/50507608 今天在使用支付宝的事后,突然发现了一个叫做芝麻信用 ...

  3. progressblock 安卓自定义进度条 progressbar 高仿仿QQ下载进度条

    progressblock 安卓自定义进度条 progressbar 高仿仿QQ下载进度条 附上我在公司做下载播放项目 主要使用方法 progressBlock = (ProgressBlock) f ...

  4. 自定义View | 仿QQ运动步数进度效果

    项目GitHub地址 思路 固定不动的蓝色大圆弧 动画变动的红色小圆弧 中间的步数文字显示 相关的自定义属性 比如固定不动的大圆弧, 我们不能写死他的蓝色颜色属性, 要提供一个颜色的自定义属性给用户自 ...

  5. 支付宝 android ui,Android 仿支付宝芝麻信用分仪表盘效果 CreditSesameRingView

    软件介绍 自定义View之仿支付宝芝麻信用分仪表盘效果,喜欢的话,请给个star,谢谢. 使用添加项目依赖Add it in your root build.gradle at the end of  ...

  6. Android仿支付宝UI功能开发,Android 自定义view仿支付宝咻一咻功能

    支付宝上有一个咻一咻的功能,就是点击图片后四周有水波纹的这种效果,今天也写一个类似的功能. 效果如下所示: 思路: 就是几个圆的半径不断在变大,这个可以使用动画缩放实现,还有透明动画 还有就是这是好几 ...

  7. Android仿IOS解锁密码界面-自定义view系列(6)

    Android仿IOS解锁密码界面-自定义view系列 功能简介 主要实现步骤-具体内容看github项目里的代码 xml相关属性设置 Android Studio 代码 Android技术生活交流 ...

  8. android 高仿 探探卡片滑动,Android自定义View仿探探卡片滑动效果

    Android自定义View仿探探卡片滑动这种效果网上有很多人已经讲解了实现思路,大多都用的是RecyclerView来实现的,但是我们今天来换一种实现思路,只用一个自定义的ViewGroup来搞定这 ...

  9. android wear支付宝6,Android自定义View仿支付宝输入六位密码功能

    跟选择银行卡界面类似,也是用一个PopupWindow,不过输入密码界面是一个自定义view,当输入六位密码完成后用回调在Activity中获取到输入的密码并以Toast显示密码.效果图如下: 自定义 ...

最新文章

  1. composer PHP Fatal error: Allowed memory size of 报错解决
  2. 台湾大学林轩田机器学习基石课程学习笔记7 -- The VC Dimension
  3. C宏定义中的##,#,#@用法介绍
  4. SAP Spartacus category navigation按钮之间的间隔问题
  5. VLfeat win10 vs2015 编译
  6. 跨过山和大海的地铁外放党们有人管了,明年开始!网友:没收手机么?
  7. 递归、搜索、贪心、动态规划的区别
  8. 腾讯云短信 Node.js SDK
  9. 如何卸载Adobe Creative Cloud
  10. win10 如何设置绿色保护色?
  11. 【eBay大赛专访特辑3】华北、中西部赛区人才济济,看他们如何乘风破浪!
  12. Python的Pexpect详解
  13. IDEA java出现无效的源发行版14解决方案
  14. 火车运煤问题 - 增加一个简单算法实现
  15. 1.U盘安装ubuntu系统
  16. 《VR入门系列教程》之2---VR头显
  17. 利用UU对GitHub国内加速优化访问
  18. C# 使用AForge调用笔记本摄像头拍照及录像
  19. 楔形文字的破解(钉子形文字)【文字破译原理:信息的相关性】
  20. 萌新带你开车上p站(番外篇)

热门文章

  1. 小程序中接口的问题及坑
  2. 闲的蛋疼:用算法解移动一根火柴问题(二)
  3. 微信小程序 页面除去头部和底部,中间高度铺满剩余部分的解决方案
  4. 从零基础学摄影nbsp;《摄影新手入…
  5. 两点之间最快的路线竟然不是直线
  6. 可持续网页设计(sustainable web design)
  7. Cisc和Risc哪一个更适合采用流水线技术来提高性能?
  8. 计算机配置方案玩游戏不卡,为什么网吧电脑配置那么低,打游戏却一点也不卡?...
  9. awakefromnib和registernib
  10. PTA - 数据库合集18