支付宝芝麻信用页面自定义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

0 0
原创粉丝点击