android开发自定义View(三)仿芝麻信用积分

此文参考了https://github.com/HotBitmapGG/CreditSesameRingView
感谢作者的分享!!

首先看一下支付宝上显示的样子

然后看一下模仿的效果

代码

基础部分就不说了,直接说核心部分,不理解的可以去看
android开发自定义View(一)
android开发自定义View(二)自定义圆形进度条

1.测量控件大小

  <cn.jiangzehui.www.myview3.MyView
        android:id="@+id/mv"
        android:padding="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
private int radus;//半径
private int defalutSize ;//默认大小
@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int wMode = MeasureSpec.getMode(widthMeasureSpec);
        int wSize = MeasureSpec.getSize(widthMeasureSpec);
        int hMode = MeasureSpec.getMode(heightMeasureSpec);
        int hSize = MeasureSpec.getSize(heightMeasureSpec);
        int width,height;
        if(wMode == MeasureSpec.EXACTLY){
            width = wSize;
        }else{
            width=Math.min(wSize,defalutSize);
        }

        if(hMode == MeasureSpec.EXACTLY){
            height = hSize;
        }else{
            height=Math.min(hSize,defalutSize);
        }
        radus = width/2;
        setMeasuredDimension(width,height);
    }

 /** * dp转px * * @param values * @return */
    public int dp_px(int values)
    {

        float density = getResources().getDisplayMetrics().density;
        return (int) (values * density + 0.5f);
    }

如果在布局中没有设定指定的大小也就是wrap_content的时候,我们需要给控制设置一个默认值defalutSize。如果不设置控件会默认全屏显示。

2.绘制外层圆环

首先初始化一下外环画笔,各种属性可根据实际情况微调。

private Paint wPaint;//外环画笔
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        defalutSize = dp_px(defalutSize);
        wPaint=new Paint();
        wPaint.setAntiAlias(true);
        wPaint.setColor(Color.WHITE);
        wPaint.setAlpha(50);//透明度,取值范围为0~255,数值越小越透明
        wPaint.setStyle(Paint.Style.STROKE);
        wPaint.setStrokeWidth(10);
    }

绘制

 @Override
    protected void onDraw(final Canvas canvas) {
        super.onDraw(canvas);

        final RectF rf=new RectF(getPaddingLeft(),getPaddingTop(),getWidth()-getPaddingRight(),getHeight()-getPaddingBottom());
        //绘制外环
        canvas.drawArc(rf,-195,210,false,wPaint);//总360
  }

效果
android开发自定义View(三)仿芝麻信用积分_第1张图片

3.绘制内层圆环

声明变量

private Paint nPaint;//内环画笔
private int distance = 30;//外环于内环的间距

在构造方法里初始化画笔

//初始化内环画笔
 distance = dp_px(distance);
 nPaint=new Paint();
 nPaint.setAntiAlias(true);
 nPaint.setColor(Color.WHITE);
 nPaint.setAlpha(50);
 nPaint.setStyle(Paint.Style.STROKE);
 nPaint.setStrokeWidth(30);

绘制

RectF n_rf=new RectF(getPaddingLeft()+distance,getPaddingTop()+distance,getWidth()-(getPaddingRight()+distance),getHeight()-(getPaddingBottom()+distance));

 //绘制内环
 canvas.drawArc(n_rf,-195,210,false,nPaint);

效果
android开发自定义View(三)仿芝麻信用积分_第2张图片

4.绘制内环刻度

声明变量

private Paint nk_Paint;//内层小刻度画笔
private Paint lfPaint;//内层大刻度画笔

初始化

nk_Paint=new Paint();
nk_Paint.setAntiAlias(true);
nk_Paint.setColor(Color.WHITE);
nk_Paint.setAlpha(80);

lfPaint=new Paint();
lfPaint.setAntiAlias(true);
lfPaint.setStrokeWidth(2);
lfPaint.setColor(Color.WHITE);
lfPaint.setAlpha(100);

绘制

        //绘制内环刻度
        canvas.save();
        canvas.rotate(-105, radus, radus);
        //计算刻度线的起点结束点
        int startDst = (int) (getPaddingLeft()+distance - nPaint.getStrokeWidth() / 2 );
        int endDst = (int) (startDst + nPaint.getStrokeWidth());
        int endDsts = (int) (startDst + nPaint.getStrokeWidth()+5);
        for (int i = 1; i <= 31; i++)
        {
            //每旋转4度绘制一个小刻度
            canvas.drawLine(radus, startDst, radus, endDst, nk_Paint);
            canvas.rotate(7, radus, radus);
        }
        canvas.restore();
        canvas.save();
        canvas.rotate(-105, radus, radus);
        for (int i = 1; i <= 6; i++)
        {
            //每旋转4度绘制一个小刻度
            canvas.drawLine(radus, startDst, radus, endDsts, lfPaint);
            canvas.rotate(42, radus, radus);
        }
        canvas.restore();

效果
android开发自定义View(三)仿芝麻信用积分_第3张图片

5.绘制内环各刻度等级,BEAT文字,信用等级,信用级别,评估时间

声明变量


    String[] str ={"350","较差","550","中等","600","良好","650","优秀","700","极好","950"};
    private Paint ztPaint;//刻度等级字体画笔
    private Paint btPaint;//BETA画笔
    private Paint szPaint;//675画笔
    private Paint djPaint;//信用等级画笔
    private Paint pgPaint;//评估时间画笔
     // 最小数字
    private int mMinNum = 350;
    // 最大数字
    private int mMaxNum = 950;
    //信用等级
    private String sesameLevel = "";
    //总进度
    private float mTotalAngle = 210f;
    //评估时间
    private String evaluationTime = "";

初始化

        ztPaint=new Paint();
        ztPaint.setAntiAlias(true);
        ztPaint.setColor(Color.WHITE);
        ztPaint.setTextSize(25);
        ztPaint.setAlpha(100);


        btPaint=new Paint();
        btPaint.setAntiAlias(true);
        btPaint.setColor(Color.WHITE);
        btPaint.setTextSize(30);
        btPaint.setAlpha(100);


        szPaint=new Paint();
        szPaint.setAntiAlias(true);
        szPaint.setColor(Color.WHITE);
        szPaint.setTextSize(140);

        djPaint=new Paint();
        djPaint.setAntiAlias(true);
        djPaint.setColor(Color.WHITE);
        djPaint.setTextSize(65);

        pgPaint=new Paint();
        pgPaint.setAntiAlias(true);
        pgPaint.setColor(Color.WHITE);
        pgPaint.setTextSize(30);
        pgPaint.setAlpha(100);

绘制

 //绘制内环各刻度等级
        canvas.save();
        canvas.rotate(-105, radus, radus);
        //计算刻度线的起点结束点
        for (int i = 0; i < str.length; i++)
        {
            //每旋转4度绘制一个小刻度
            float textLen = ztPaint.measureText(str[i]);
            canvas.drawText(str[i],radus - textLen / 2,endDst + 40,ztPaint);
            canvas.rotate(21, radus, radus);
        }
        canvas.restore();

        //绘制BEAT文字
        Rect rt=new Rect();
        btPaint.getTextBounds("BETA",0,"BETA".length(),rt);
        float beta_hight = rt.height();
        float beta_width = rt.width();
        canvas.drawText("BETA",radus - beta_width / 2,radus/2,btPaint);


        //绘制信用等级
        Rect rt1=new Rect();
        if(mMinNum!=0){
            szPaint.getTextBounds("111",0,"111".length(),rt1);
            float textLen1 = szPaint.measureText(mMinNum+"");
            canvas.drawText(mMinNum+"",radus - textLen1 / 2,radus/2+beta_hight+rt1.height(),szPaint);
        }


        //绘制信用级别
        Rect rt2=new Rect();
        djPaint.getTextBounds(sesameLevel,0,sesameLevel.length(),rt2);
        float textLen2 = djPaint.measureText(sesameLevel);
        canvas.drawText(sesameLevel,radus - textLen2 / 2,radus/2+beta_hight*2+rt2.height()+rt1.height(),djPaint);

        //绘制评估时间
        Rect rt3=new Rect();
        pgPaint.getTextBounds(evaluationTime,0,evaluationTime.length(),rt3);
        float textLen3 = pgPaint.measureText(evaluationTime);
        canvas.drawText(evaluationTime,radus - textLen3 / 2,radus/2+beta_hight*3+rt2.height()+rt1.height()+rt3.height(),pgPaint);

方法

/** * 获取当前时间 * * @return */
    public String getCurrentTime()
    {

        @SuppressLint("SimpleDateFormat")
        SimpleDateFormat format = new SimpleDateFormat("yyyy:MM:dd");
        return format.format(new Date());
    }

//数字动画
    public void startAnim()
    {

        ValueAnimator mAngleAnim = ValueAnimator.ofFloat(progress, mTotalAngle);
        mAngleAnim.setInterpolator(new AccelerateDecelerateInterpolator());
        mAngleAnim.setDuration(5000);
        mAngleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
        {

            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator)
            {

                progress = (float) valueAnimator.getAnimatedValue();
                postInvalidate();
            }
        });
        mAngleAnim.start();



        ValueAnimator mNumAnim = ValueAnimator.ofInt(mMinNum, mMaxNum);
        mNumAnim.setDuration(5000);
        mNumAnim.setInterpolator(new LinearInterpolator());
        mNumAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
        {

            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator)
            {

                mMinNum = (int) valueAnimator.getAnimatedValue();
                postInvalidate();
            }
        });
        mNumAnim.start();
    }


//设置信用等级350~950之间
    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();
    }

在Activity初始化并调用

mv= (MyView) findViewById(R.id.mv);
mv.setSesameValues(657);

效果

android开发自定义View(三)仿芝麻信用积分_第4张图片
大体样子已经基本出来了

6. 绘制进度条

  private Paint mBitmapPaint;//小圆点画笔
  private float[] cir_location;//小圆点的实际位置
        mBitmapPaint = new Paint();
        mBitmapPaint.setStyle(Paint.Style.FILL);
        mBitmapPaint.setColor(Color.WHITE);
        mBitmapPaint.setAntiAlias(true);
        cir_location = new float[2];
 //绘制外环进度
 canvas.drawArc(rf,-195,progress,false,wwPaint);//总360
//绘制外环小圆点
        Path path = new Path();
        path.addArc(rf, -195, progress);
        PathMeasure pathMeasure = new PathMeasure(path, false);
        pathMeasure.getPosTan(pathMeasure.getLength() * 1, cir_location, null);
        mBitmapPaint.setColor(Color.WHITE);
        canvas.drawCircle(cir_location[0], cir_location[1], 8, mBitmapPaint);
        canvas.drawCircle(cir_location[0], cir_location[1], 8, mBitmapPaint);

源码下载

你可能感兴趣的:(Android开发)