自定义View,仿蚂蚁芝麻分仪表盘(早前的一版)

整理代码,发现了这个3年前写的一个view,记得当时也是参考了某大佬的博客写的,记不清了,因为这个view还是有一些知识点的,所以写下来记录一下吧

先看下最后的效果

 

上代码,具体的细节,在代码中参悟吧

样式

    <declare-styleable name="RoundIndicatorView">
        <!--最大数值-->
        <attr name="maxNum" format="integer"/>
        <!--圆盘起始角度-->
        <attr name="startAngle" format="integer"/>
        <!--圆盘扫过的角度-->
        <attr name="sweepAngle" format="integer"/>
    </declare-styleable>

代码

package com.xinxin.applicationtest.widget;

import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import com.xinxin.applicationtest.R;

/**
 * Created by wxx on 2016/12/5  0005.
 * 作用 : 仿支付宝芝麻信用分
 */

public class IndicatorView extends View {
    private int sweepInWidth;//内圆弧宽度
    private int sweepOutWidth;//外圆弧宽度

    private int maxNum;//最大分值
    private int currentNum = 1;//当前分值

    private int startAngle;//圆弧开始的角度
    private int sweepAngle;//圆弧的结束的角度

    private int mWidth;//视图的宽
    private int mHeight;//视图的高

    private Paint paint;
    private Paint paint_2;
    private Paint paint_3;
    private Paint paint_4;

    private int radius;//圆弧半径


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

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

    public IndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setBackgroundColor(0xFFFF6347);
        initAttr(attrs);
        initPaint();
    }

    private void initAttr(AttributeSet attributeSet) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attributeSet, R.styleable.RoundIndicatorView);
        maxNum = typedArray.getInt(R.styleable.RoundIndicatorView_maxNum,500);
        startAngle = typedArray.getInt(R.styleable.RoundIndicatorView_startAngle, 160);
        sweepAngle = typedArray.getInt(R.styleable.RoundIndicatorView_sweepAngle, 220);
        sweepInWidth = dp2px(8);
        sweepOutWidth = dp2px(3);
        typedArray.recycle();
    }

    public int getCurrentNum() {
        return currentNum;
    }

    public void setCurrentNum(int currentNum) {
        this.currentNum = currentNum;
        invalidate();
    }

    public void setCurrentNumAnim(int num) {
        float duration = (float)Math.abs(num-currentNum)/maxNum *1500+500; //根据进度差计算动画时间
        ObjectAnimator anim = ObjectAnimator.ofInt(this,"currentNum",num);
        anim.setDuration((long) Math.min(duration,2000));
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
                int color = calculateColor(value);
                setBackgroundColor(color);
            }
        });
        anim.start();
    }
    private int calculateColor(int value){
        setCurrentNum(value);
        ArgbEvaluator evealuator = new ArgbEvaluator();
        float fraction = 0;
        int color = 0;
        if(value <= maxNum/2){
            fraction = (float)value/(maxNum/2);
            color = (int) evealuator.evaluate(fraction,0xFFFF6347,0xFFFF8C00); //由红到橙
        }else {
            fraction = ( (float)value-maxNum/2 ) / (maxNum/2);
            color = (int) evealuator.evaluate(fraction,0xFFFF8C00,0xFF00CED1); //由橙到蓝
        }
        return color;
    }

    /**
     * 初始化所有画笔
     */
    private void initPaint() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setDither(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(0xffffffff);
        paint_2 = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint_3 = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint_4 = new Paint(Paint.ANTI_ALIAS_FLAG);

    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (widthMode == MeasureSpec.EXACTLY) {
            mWidth = widthSize;
        } else {
            mWidth = dp2px(300);
        }
        if (heightMode == MeasureSpec.EXACTLY) {
            mHeight = heightSize;
        } else {
            mHeight = dp2px(400);
        }
        setMeasuredDimension(mWidth,mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        radius = getMeasuredWidth()/4;
        canvas.translate(mWidth /2, mHeight /2);
        drawRound(canvas);  //画内外圆弧
        drawScale(canvas);//画圆弧上的刻度
        drawIndicator(canvas);//画分值指示器
        drawCenterText(canvas);//画中间的字
        canvas.restore();
    }

    private String[] text ={"较差","中等","良好","优秀","极好"};

    /** 化圆弧上的刻度 */
    private void drawScale(Canvas canvas) {
        canvas.save();
        canvas.rotate(startAngle - 270);
        float count = (float)sweepAngle / 30;
        for (int i = 0; i <= 30; i++) {
            if (i % 6 == 0) {
                paint.setStrokeWidth(dp2px(3));
                canvas.drawLine(0, -radius - sweepInWidth / 2, 0, -radius + sweepInWidth / 2 + dp2px(2), paint);
                paint.setAlpha(0x90);
                drawText(canvas, String.valueOf(maxNum / 30 * i), paint);
            } else {
                paint.setStrokeWidth(dp2px(1));
                canvas.drawLine(0, -radius - sweepInWidth / 2, 0, -radius + sweepInWidth / 2, paint);
                paint.setAlpha(0x50);
            }
            if(i == 3 || i == 9 || i == 15 || i ==21 || i == 27) {
                drawText(canvas,text[(int)i/6],paint);
            }
            canvas.rotate(count);
        }
        canvas.restore();
    }

    /** 画刻度下方对应的分值 */
    private void drawText(Canvas canvas, String score, Paint paint) {
        paint.setStyle(Paint.Style.FILL);
        paint.setTextSize(dp2px(10));
        float width = paint.measureText(score);
        canvas.drawText(score,-width/2,-radius + sweepInWidth/2 + dp2px(15),paint);
        paint.setStyle(Paint.Style.STROKE);
    }

    private void drawRound(Canvas canvas) {
        //内圆
        canvas.save();
        paint.setAlpha(0x40);
        paint.setStrokeWidth(sweepInWidth);
        RectF rectf = new RectF(-radius,-radius,radius,radius);
        canvas.drawArc(rectf,startAngle,sweepAngle,false,paint);
        //外圆
        paint.setStrokeWidth(sweepOutWidth);
        int w = dp2px(10);
        RectF rectf2 = new RectF(-radius-w , -radius-w , radius+w , radius+w);
        canvas.drawArc(rectf2,startAngle,sweepAngle,false,paint);
        canvas.restore();
    }

    private int[] indicatorColor = {0xffffffff,0x00ffffff,0x99ffffff,0xffffffff};

    /** 画外边缘的分值指示器 */
    private void drawIndicator(Canvas canvas) {
        canvas.save();
        float sweep = (float) currentNum / (float) maxNum * sweepAngle;
        if(currentNum > maxNum) {
            sweep = sweepAngle;
        }
        SweepGradient sweepGradient = new SweepGradient(0, 0, indicatorColor, null);
        paint_2.setShader(sweepGradient);
        paint_2.setStyle(Paint.Style.STROKE);
        paint_2.setStrokeWidth(sweepOutWidth);
        int w = dp2px(10);
        RectF rectF = new RectF(-radius - w, -radius - w, radius + w, radius + w);
        canvas.drawArc(rectF,startAngle,sweep,false,paint_2);


        float x = (float) ((radius+dp2px(10))*Math.cos(Math.toRadians(startAngle+sweep)));
        float y = (float) ((radius+dp2px(10))*Math.sin(Math.toRadians(startAngle+sweep)));
        paint_3.setStyle(Paint.Style.FILL);
        paint_3.setColor(0xffffffff);
        paint_3.setMaskFilter(new BlurMaskFilter(dp2px(3), BlurMaskFilter.Blur.SOLID)); //需关闭硬件加速
        canvas.drawCircle(x,y,dp2px(3),paint_3);
        canvas.restore();
    }


    /** 画中间的字 */
    private void drawCenterText(Canvas canvas) {
        canvas.save();
        paint_4.setTextSize(radius/2);
        paint_4.setColor(0xffffffff);
        canvas.drawText(String.valueOf(currentNum),-paint_4.measureText(String.valueOf(currentNum))/2,0,paint_4);
        String content = "信用";
        if(currentNum < maxNum*1/5){
            content += text[0];
        }else if(currentNum >= maxNum*1/5 && currentNum < maxNum*2/5){
            content += text[1];
        }else if(currentNum >= maxNum*2/5 && currentNum < maxNum*3/5){
            content += text[2];
        }else if(currentNum >= maxNum*3/5 && currentNum < maxNum*4/5){
            content += text[3];
        }else if(currentNum >= maxNum*4/5){
            content += text[4];
        }

        paint_4.setTextSize(radius/4);
        Rect rect = new Rect();
        paint_4.getTextBounds(content,0,content.length(),rect);
        canvas.drawText(content,-rect.width()/2,rect.height(),paint_4);
        canvas.restore();
    }

    //一些工具方法
    protected int dp2px(int dp){
        return (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                dp,
                getResources().getDisplayMetrics());
    }
    protected int sp2px(int sp){
        return (int)TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_SP,
                sp,
                getResources().getDisplayMetrics());
    }
}

xml中引用

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_credit_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    tools:context="com.xinxin.applicationtest.CreditViewActivity">
    <com.xinxin.applicationtest.widget.IndicatorView
        android:id="@+id/viewOne"
        android:layout_width="wrap_content"
        android:background="@android:color/holo_blue_dark"
        android:layout_height="200dp" />
    <EditText
        android:id="@+id/etScore"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="start"/>
</LinearLayout>

如果使用

package com.xinxin.applicationtest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;

import com.xinxin.applicationtest.widget.IndicatorView;

public class CreditViewActivity extends AppCompatActivity {
    private IndicatorView viewOne;
    private EditText etScore;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_credit_view);

        viewOne = (IndicatorView)findViewById(R.id.viewOne);
        etScore = (EditText)findViewById(R.id.etScore);
    }

    public void start(View v) {
        String trim = etScore.getText().toString().trim();
        viewOne.setCurrentNumAnim(Integer.parseInt(trim));
    }
}

 

整理公司电脑,这开发过程中下载过很多的第三方库、demo啥玩意的,特别多,好几年了,电脑上到处都是一些第三方的代码,想着整理一下,清理清理没用的,所以基本都是把每一个demo都跑一下看看是什么东西,没用的就删了,发现了这个当时写的,觉得这个里边还有一些不错的view绘制的知识点和关键API,就写下来吧。

单看是不行的,需要参悟一下view绘制过程中的一些边、弧的算法。

还有一个是芝麻信用分分析图的 点击查看 https://blog.csdn.net/wxx_csdn/article/details/90714774

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自定义View仿支付宝芝麻信用仪表盘效果,喜欢的话,请给个star,谢谢.使用添加项目依赖Add it in your root build.gradle at the end of repositories: allprojects {         repositories { ... maven { url "https://jitpack.io" }         }     } Add the dependency     dependencies {             compile 'com.github.HotBitmapGG:CreditSesameRingView:V1.0.2' }新版芝麻信用使用     // The gradient color can define your own private final int[] mColors = new int[]{             0xFFFF80AB,             0xFFFF4081,             0xFFFF5177,             0xFFFF7997              }; // Set up the need to score mLayout = (RelativeLayout) view.findViewById(R.id.layout);       mButton = (Button) view.findViewById(R.id.btn);       newCreditSesameView = (NewCreditSesameViewview.findViewById(R.id.sesame_view);       mLayout.setBackgroundColor(mColors[0]);       mButton.setOnClickListener(new View.OnClickListener()       { @Override public void onClick(View view)            {                newCreditSesameView.setSesameValues(639);                startColorChangeAnim();            }       }); // The background color gradient animation Simply illustrates the effect Can customize according to your need public void startColorChangeAnim()      { ObjectAnimator animator = ObjectAnimator.ofInt(mLayout, "backgroundColor", mColors);          animator.setDuration(3000);          animator.setEvaluator(new ArgbEvaluator());          animator.start();      }旧版芝麻信用使用      // Set up the need to score oldCreditSesameView = (OldCreditSesameViewview.findViewById(R.id.sesame_view);       mButton = (Button) view.findViewById(R.id.btn);       mButton.setOnClickListener(new View.OnClickListener()       { @Override public void onClick(View view)           {               oldCreditSesameView.setSesameValues(639);           }       });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值