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:



    

        
        
        
        

        
        
        

        
        
        

        

        
        

        

    


布局文件:

    



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