支付宝芝麻信用页面自定义View的简单制作(续)
来源:互联网 发布:中考历史真题 淘宝 编辑:程序博客网 时间:2024/04/30 21:10
前两个月刚刚写了一篇关于支付宝芝麻信用页面自定义View的总结,感觉写的不太好,链接如下:
http://blog.csdn.net/anny_lin/article/details/49474555
当时写的时候没有考虑到布局的问题,当移动View的时候,view就出现绘图错乱了,还好有个哥们看了给我提醒了一下,最近刚好比较闲,就寻思重新记录一下写自定义View的过程,算是对自定义View的一个小的总结吧,顺便把遇到过的坑记录一下,提醒一下自己。
注意:这篇文章针对http://blog.csdn.net/anny_lin/article/details/49474555
出现的布局问题作修改,其他实现参考上面链接
废话不多说,首先看看,人家支付宝芝麻信用的页面吧:
上图展示的就是一个支付宝信用的一个页面,我们从页面的构造开始分析:
最上面的视图我们并不需要自定义,直接使用textView即可,主要需要自定义的模块就只有中间那一部分,我们把它单独拿出来分析一下:
我们可以看到它是由两个半圆环,即外面的半圈圈构成,思考一下,在使用
canvas.drawArc(rectF,165, 210,false,outArcPaint);
这个api就可以搞定了,我们还能发现在第二个圆圈里面有刻度线着写小东东,同样视图最内层还有刻度线的说明,这个我们需要怎么做呢?思考一下,我们可以通过不断地旋转画布定点绘制,当画布旋转完成我们刻度线和刻度线下方的字体就可以完成啦。
接下来就是要写中间的字了,调用
canvas.drawText(numString,centerX-textWidth/2,centerY,textPaint);
即可,还是很容易的,我们的静态效果到这就分析完成了,我们看看代码的实现方式:
重写的onMeasure()方法:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int wrap_Len = DensityUtil.dip2px(context, 300); int width = measureDimension(wrap_Len, widthMeasureSpec); int height = measureDimension(wrap_Len, heightMeasureSpec); len=Math.min(width,height); //保证他是一个正方形 setMeasuredDimension(len,len); } public int measureDimension(int defaultSize, int measureSpec){ int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if(specMode == MeasureSpec.EXACTLY){ result = specSize; }else{ result = defaultSize; //UNSPECIFIED if(specMode == MeasureSpec.AT_MOST){ result = Math.min(result, specSize); } } return result; }
我们这里保证这个View是一个正方形的效果,防止视图太难看。
初始化工具类:
private void init() { //两外圈的距离 distance_from_two_acr=DensityUtil.dip2px(context,14); //外圈画笔 outArcPaint=new Paint(); outArcPaint.setAntiAlias(true); outArcPaint.setStrokeWidth(8); outArcPaint.setColor(Color.parseColor("#ffee44")); outArcPaint.setStyle(Paint.Style.STROKE); //内圈画笔 inArcPaint=new Paint(); inArcPaint.setAntiAlias(true); inArcPaint.setStrokeWidth(30); inArcPaint.setColor(Color.parseColor("#ffffff")); inArcPaint.setAlpha(120); inArcPaint.setStyle(Paint.Style.STROKE); //正中间字体画笔 textPaint=new Paint(Paint.ANTI_ALIAS_FLAG); textPaint.setTextSize(60); textPaint.setColor(Color.parseColor("#ffffff")); }
上述初始化了一些画笔工具以及一些变量,这里就不详细的去说明paint各个方法的含义了,不懂得同学请度娘。
重点来了:
最重要的方法就是我们的onDraw()方法了,所有的自定义View一般都要重写此方法进行视图的绘制:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //获得中心点坐标 int centerX= len/2; int centerY= len/2; Log.e("the center is","centerX="+centerX+" centerY"+centerY); //只要传入相对的坐标即可,画最最外圈的圆环 RectF rectF=new RectF(0+DEFAULT_PADDING,0+DEFAULT_PADDING ,getMeasuredWidth()-DEFAULT_PADDING,getMeasuredHeight()-DEFAULT_PADDING); canvas.drawArc(rectF,165, 210,false,outArcPaint); //内圆环画圈 rectF=new RectF(0+DEFAULT_PADDING+distance_from_two_acr,0+DEFAULT_PADDING+distance_from_two_acr,getMeasuredWidth()-DEFAULT_PADDING-distance_from_two_acr ,getMeasuredHeight()-DEFAULT_PADDING-distance_from_two_acr); canvas.drawArc(rectF,165, 210,false,inArcPaint); //中间字体的绘制 drawText(canvas,centerX,centerY); //进行内圆环刻度线的draw drawtheLine(canvas,centerX,centerY); } private void drawtheLine(Canvas canvas,int centerX,int centerY) { canvas.save(); //我们将画布旋转,实际上是旋转我们的坐标轴 canvas.rotate(-105,getMeasuredWidth()/2,getMeasuredHeight()/2); int lineStartY= (int) (DEFAULT_PADDING+distance_from_two_acr-inArcPaint.getStrokeWidth()/2-1); int lineEndY= (int) (lineStartY+inArcPaint.getStrokeWidth()); //每次画布旋转的角度 int rotateRadius=210/10; for(int i=1;i<12;i++){ if (i%2==0){ canvas.drawLine(centerX, lineStartY, centerX, lineEndY, keduDarkPaint); }else { canvas.drawLine(centerX, lineStartY, centerX, lineEndY, keduLightPaint); } float textLength=keduFontPaint.measureText(stringArray[i-1]); canvas.drawText(stringArray[i-1],centerX-textLength/2,lineEndY+30,keduFontPaint); canvas.rotate(rotateRadius,centerX,centerY); } canvas.restore(); } private void drawText(Canvas canvas,int centerX,int centerY){ if (!TextUtils.isEmpty(textString)){ //计算字体的长度 float textWidth=textPaint.measureText(textString); //textPaint.descent()-textPaint.ascent()测量字体高度 canvas.drawText(textString,centerX-textWidth/2,centerY+10+(textPaint.descent()-textPaint.ascent()),textPaint); } if (!TextUtils.isEmpty(textString)){ float textWidth=textPaint.measureText(numString); canvas.drawText(numString,centerX-textWidth/2,centerY,textPaint); } }
最麻烦的无非是坐标的计算,这里就不详细的讲了,要讲可能要将一大堆,所以就不详述了,这里讲几个需要注意的地方:
1.当我们使用一些canvas方法的时候,我们需要知道方法中的坐标都是相对于本身View而言的,一般而言,我们并不需要考虑使用getX()或者getY()来进行坐标的计算的,否则当我们改变布局的位置的时候,是会引起坐标的错位问题的,这个很重要!
2.当考虑到旋转画布的问题的时候,坐标的计算方面会比较抽象,可能花的时间会很多,需要深入了解canvas.rotate()的工作原理,这一方面我自己也有点晕忽忽的,网上很多人讲的都不一样,有时间的时候需要多加研究一下。
我们静态的页面到这里算是完成了,我们看一下效果图:
我们可以看到修改了布局后,自定的View效果保持一致,这正是我们所需要的,好的,接下来我们就需要让图动起来了,我们分别需要一个类似于progreeBar的圆环动态效果,一个背景渐变效果,这里不考虑数字变化的动态效果,网上好像有着方面的控件,自己实现可能有一定的难度,所以我们考虑progreeBar的圆环动态效果和背景渐变效果实现:
1.圆环动态效果,我们可以通过view.post方法进行重绘的操作
2.背景渐变,属性动画中提供了这个api,我们也可以实现
由于这篇文章已经实现过了,这里就不叙述了,这篇文章主要解决布局错乱的问题
代码:
//背景渐变动画实现 ValueAnimator coloranim= ObjectAnimator.ofInt(context, "backgroundColor", 0xFFFF8080, 0xFF8080FF); coloranim.setDuration(30 * 180); coloranim.setEvaluator(new ArgbEvaluator()); coloranim.start();
更新条的实现:
post(new Runnable() { @Override public void run() { if (start<arcEnd){ start+=(20/7); postInvalidateDelayed(10); } } });
最后的效果:
上述的Demo下载地址:
https://github.com/JerryChan123/android-learning/tree/master
- 支付宝芝麻信用页面自定义View的简单制作(续)
- 自定义View实现支付宝芝麻信用页面功能
- 第一章 仿支付宝芝麻信用界面制作(需要自定义View的相关知识)
- Android自定义view之仿支付宝芝麻信用仪表盘
- Android 自定义控件 仿支付宝芝麻信用的刻度盘
- Android自定义view之仿支付宝芝麻信用仪表盘 ---by ccy
- 如何提高支付宝芝麻信用的分数
- 支付宝芝麻信用UI_(一)基本功能的实现
- 支付宝里面的芝麻信用有什么用?
- 【圈子】提升支付宝芝麻信用评分
- 支付宝授权获取芝麻信用分数
- 自定义view-仿支付宝芝麻分圆盘
- Android 仿支付宝9.0芝麻信用分效果
- Android仿支付宝9.5芝麻信用分仪表盘
- android模拟支付宝芝麻信用(上)
- iOS仿支付宝芝麻信用仪表盘效果
- android开发自定义View(三)仿芝麻信用积分
- 简单的自定义view制作
- Linux 文件操作总结
- 手把手教你如何访问谷歌
- Ubuntu上为Android编写驱动程序
- 全景拼接实现过程
- Spring+EhCache缓存实例(详细讲解+源码下载)
- 支付宝芝麻信用页面自定义View的简单制作(续)
- 回顾一些重要的CNN改进模型(你真的了解 Convolutional Neural Networks 么)
- 悲观锁和乐观锁
- Android之编写C程序访问Android之驱动程序
- Linux下umask命令的用法
- 【CCF】高速公路
- 八步详解Hibernate的搭建及使用
- Android之测试Jave接口访问硬件服务
- Andorid之为何要用到NDK?