android自定义控件-模仿支付宝信用表盘

 自定义控件流程:

1.在attr中添加自定义属性
2.在xml中设置属性
3.写一个自定义属性的类在构造方法中获得xml设置的属性
4.重写onmeassure 和onDraw方法


代码:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.example.administrator.yihaodai.R;

/**
 * Created by Administrator on 2017/3/26.
 */

public class CustomXinyongView extends View {

    //半径
    private int bigCircleRadio;
    private int smallDashRadio;
    private int scoreRadio;

    //线宽
    private int bigCircleStrokeWidth;
    private int smallDashStrokeWidth;
    private int scorePointWidth;

    //颜色
    private int bigCircleColor;
    private int bigCirecleBackColor;
    private int scorePointColor;
    private int smallDashColor;

    //字体大小
    private int titleSize;
    private int detailSize;

    //字符串
    private String mtitle = "50";
    private String detail = "信用中等";

    //分数
    private int mScore;


    //圆心位置
    private int cx;
    private int cy;


    public CustomXinyongView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomXinyongView, 0, 0);
        //获取颜色
        bigCirecleBackColor = typedArray.getColor(R.styleable.CustomXinyongView_big_circle_back_color, 0xffffaa00);
        bigCircleColor = typedArray.getColor(R.styleable.CustomXinyongView_big_circle_color, 0xffff6600);
        scorePointColor = typedArray.getColor(R.styleable.CustomXinyongView_score_point_color, 0xffff6600);
        smallDashColor = typedArray.getColor(R.styleable.CustomXinyongView_small_dash_color, 0xffffaa00);

        //获取半径 用dimension好像会变形
        bigCircleRadio = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_big_circle_radio, 200);
        smallDashRadio = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_small_dash_radio, 120);
        scoreRadio = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_socre_point_radio, 90);

        //获取线宽
        bigCircleStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_big_circle_stroke_width, 10);
        smallDashStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_small_dash_stroke_width, 10);
        scorePointWidth = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_score_point_stroke_width, 3);

        //分数
        mScore = typedArray.getInteger(R.styleable.CustomXinyongView_mScore, 50);

        //获取字体大小
        titleSize = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_titleSize, 60);
        detailSize = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_detailSize, 30);

        //获取字符串
        mtitle = String.valueOf(mScore);
        detail = typedArray.getString(R.styleable.CustomXinyongView_detail_text);

        //圆心位置
        cx = bigCircleRadio + getPaddingLeft();
        cy = bigCircleRadio + getPaddingTop();
    }

    @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);

        int width;
        int height;
        //
        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
            cx = width / 2;
        } else {
            width = 2 * cx;
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = 2 * cy;
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //虚线小圆
        initDashCircle(canvas, smallDashColor, smallDashRadio);
        //大圆背景
        initScoreCircle(canvas, 100, bigCirecleBackColor, bigCircleRadio);
        //分数盘
        initScoreCircle(canvas, mScore, bigCircleColor, bigCircleRadio);
        //指针
        initScorePoint(canvas, mScore, scorePointColor);

        initTitleText(canvas);
        initScore(canvas);
    }


    /**
     * 画小圆虚线
     *
     * @param canvas
     * @param color
     * @param smallDashRadio
     */
    private void initDashCircle(Canvas canvas, int color, int smallDashRadio) {

        //画笔
        Paint paint = new Paint();
        paint.setColor(color);
        paint.setAntiAlias(true);//抗锯齿
        paint.setStrokeWidth(smallDashStrokeWidth);//设置线宽
        paint.setStyle(Paint.Style.STROKE);//设置空心

        float pointLength = (float) (2 * Math.PI * smallDashRadio * 2 / 3 / 205);//设置分割线
        paint.setPathEffect(new DashPathEffect(new float[]{pointLength, pointLength * 11, pointLength, pointLength * 11}, 0));

        //位置和大小
        RectF rectF = new RectF(cx - smallDashRadio, cy - smallDashRadio, cx + smallDashRadio, cy + smallDashRadio);//半径100,圆心200.200

        //画弧线
        canvas.drawArc(rectF, 150, 240, false, paint);

    }

    /**
     * 画指针
     *
     * @param canvas
     * @param score
     * @param color
     */
    private void initScorePoint(Canvas canvas, int score, int color) {
        if (score <= 0) {
            score = 1;
        }
        //1.绘制圆
        Paint paint = new Paint();
        int paintWidth = scorePointWidth;
        //画笔
        paint.setColor(color);
        paint.setAntiAlias(true);//抗锯齿
        paint.setStrokeWidth(paintWidth);//设置线宽
        paint.setStyle(Paint.Style.FILL_AND_STROKE);//设置实心

        //画圆
        float cx1 = (float) (cx + scoreRadio * Math.cos(Math.toRadians(210 - score * 240 / 100)));
        float cy1 = (float) (cy - scoreRadio * Math.sin(Math.toRadians(210 - score * 240 / 100)));
        float circlePointRadio = paintWidth * 2;
        canvas.drawCircle(cx1, cy1, circlePointRadio, paint);


        //2.绘制三角形
        //A点坐标
        float pointAx = (float) (cx + (scoreRadio + 2 * paintWidth * 2) * Math.cos(Math.toRadians(210 - score * 240 / 100)));
        float pointAy = (float) (cy - (scoreRadio + 2 * paintWidth * 2) * Math.sin(Math.toRadians(210 - score * 240 / 100)));
        //获得B和C点的坐标
        //b和c点到圆心的距离
        float lBC1 = (float) (Math.sqrt(3) / 2 * circlePointRadio);//短边
        float lBC2 = (scoreRadio + circlePointRadio / 2);//长边
        float lBC = (float) Math.sqrt(Math.pow(lBC1, 2) + Math.pow(lBC2, 2));//斜边
        //B点的角度和坐标
        double aphaB = Math.toRadians(210 - score * 240 / 100) - Math.asin(lBC1 / lBC);
        float pointBx = (float) (cx + (lBC) * Math.cos(aphaB));
        float pointBy = (float) (cy - (lBC) * Math.sin(aphaB));
        //C点的角度和坐标
        double aphaC = Math.toRadians(210 - score * 240 / 100) + Math.asin(lBC1 / lBC);
        float pointCx = (float) (cx + (lBC) * Math.cos(aphaC));
        float pointCy = (float) (cy - (lBC) * Math.sin(aphaC));

        Path path = new Path();
        path.moveTo(pointAx, pointAy);// 此点为多边形的起点
        path.lineTo(pointBx, pointBy);
        path.lineTo(pointCx, pointCy);
        path.close(); // 使这些点构成封闭的多边形
        canvas.drawPath(path, paint);

        //空心
        paint.setStyle(Paint.Style.FILL);//设置实心
        paint.setColor(Color.WHITE);
        canvas.drawCircle(cx1, cy1, circlePointRadio / 2, paint);

    }


    /**
     * 画大圆(背景/分数线)
     *
     * @param canvas
     * @param score
     * @param color
     * @param bigCircleRadio
     */
    private void initScoreCircle(Canvas canvas, int score, int color, int bigCircleRadio) {
        if (score == 0) {
            score = 1;
        }

        int paintWide = bigCircleStrokeWidth;
        //画笔
        Paint paint = new Paint();
        paint.setColor(color);
        paint.setAntiAlias(true);//抗锯齿
        paint.setStrokeWidth(paintWide);//设置线宽
        paint.setStyle(Paint.Style.STROKE);//设置空心
        //位置和大小
        RectF rectF = new RectF(cx - bigCircleRadio, cy - bigCircleRadio, cx + bigCircleRadio, cy + bigCircleRadio);
        //画弧线
        canvas.drawArc(rectF, 150, score * 240 / 100, false, paint);

        //画圆
        float cx1 = (float) (cx + bigCircleRadio * Math.cos(Math.toRadians(210)));
        float cy1 = (float) (cy - bigCircleRadio * Math.sin(Math.toRadians(210)));
        float cx2 = (float) (cx + bigCircleRadio * Math.cos(Math.toRadians(210 - score * 240 / 100)));
        float cy2 = (float) (cy - bigCircleRadio * Math.sin(Math.toRadians(210 - score * 240 / 100)));
        paint.setStrokeWidth(paintWide / 2);
        canvas.drawCircle(cx1, cy1, paintWide / 4, paint);
        canvas.drawCircle(cx2, cy2, paintWide / 4, paint);
    }


    /**
     * 初始化Title
     *
     * @param canvas
     */
    private void initTitleText(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(bigCircleColor);
        paint.setTextSize(titleSize);//设置字体大小
        paint.setAntiAlias(true);//抗锯齿
        Rect bound = new Rect();
        paint.getTextBounds(mtitle, 0, mtitle.length(), bound);
        int textWidth = bound.width();
        canvas.drawText(mtitle, cx - textWidth / 2, cy, paint);

    }

    /**
     * 初始化分数
     *
     * @param canvas
     */
    private void initScore(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(smallDashColor);
        paint.setAntiAlias(true);//抗锯齿

        paint.setTextSize(detailSize);//设置字体大小

        Rect bound = new Rect();
        paint.getTextBounds(detail, 0, detail.length(), bound);
        int textWidth = bound.width();

        canvas.drawText(detail, cx - textWidth / 2, (int) (cy + detailSize * 1.5), paint);

    }

    public void setScore(int score) {
        // TODO: 2017/3/27 设置分数,可以在这里做刷新动画和更改信用评级
        mScore = score;
        mtitle = String.valueOf(mScore);
        postInvalidate();//刷新界面
    }


}

attr:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomXinyongView">

        <attr name="big_circle_back_color" format="color" />
        <attr name="big_circle_color" format="color" />
        <attr name="small_dash_color" format="color"/>
        <attr name="score_point_color" format="color"/>

        <attr name="big_circle_radio" format="dimension"/>
        <attr name="small_dash_radio" format="dimension"/>
        <attr name="socre_point_radio" format="dimension"/>

        <attr name="big_circle_stroke_width" format="dimension"/>
        <attr name="small_dash_stroke_width" format="dimension"/>
        <attr name="score_point_stroke_width" format="dimension"/>

        <attr name="detail_text" format="string"/>

        <attr name="titleSize" format="dimension"/>
        <attr name="detailSize" format="dimension"/>

        <attr name="mScore" format="integer" />

    </declare-styleable>

</resources>

布局文件:

    <com.example.administrator.samplecustomxinyongview.CustomXinyongView
        android:id="@+id/xinyongview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:padding="20dp"

        app:big_circle_radio="100dp"
        app:small_dash_radio="80dp"
        app:socre_point_radio="60dp"

        app:big_circle_stroke_width="10dp"
        app:small_dash_stroke_width="10dp"
        app:score_point_stroke_width="4dp"
        app:mScore="50"
        app:detail_text="信用中等"

        android:onClick="click"
        />



自定义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 = (NewCreditSesameView) view.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 = (OldCreditSesameView) view.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、付费专栏及课程。

余额充值