Canvas



一.drawCircle

(1)Fill And Stroke

public class CanvasView extends View {

    private Paint mPaint;
    private Context mContext;

    public CanvasView(Context context) {
        super(context);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mPaint = new Paint();
        mContext = context;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int roundWidth = dp2px(20);
        float center = getWidth() / 2;
        mPaint.setColor(Color.BLUE);

mPaint.setStyle(Paint.Style.FILL_AND_STROKE);

mPaint.setStrokeWidth(roundWidth);
        //去掉锯齿
        mPaint.setAntiAlias(true);
        //所画圆的中心 X坐标
        //所画圆的中心 Y坐标
        //所画圆的半径
        //画圆要用的画笔
        //drawCircle(float cx, float cy, float radius, Paint paint)
        canvas.drawCircle(center, center, center - roundWidth / 2, mPaint);
    }

    public int dp2px(int dp) {
        return (int) (dp * mContext.getResources().getDisplayMetrics().density + 0.5f);
    }
}

(2)Fill

<pre name="code" class="java">@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int roundWidth = dp2px(20);
    float center = getWidth() / 2;
    mPaint.setColor(Color.BLUE);

 

mPaint.setStyle(Paint.Style.FILL);

mPaint.setStrokeWidth(roundWidth);
    //去掉锯齿
    mPaint.setAntiAlias(true);
    //所画圆的中心 X坐标
    //所画圆的中心 Y坐标
    //所画圆的半径
    //画圆要用的画笔
    //drawCircle(float cx, float cy, float radius, Paint paint)
    canvas.drawCircle(center, center, center - roundWidth / 2, mPaint);
}

(3)Stroke

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int roundWidth = dp2px(20);
    float center = getWidth() / 2;
    mPaint.setColor(Color.BLUE);
mPaint.setStyle(Paint.Style.STROKE);
 mPaint.setStrokeWidth(roundWidth);
    //去掉锯齿
    mPaint.setAntiAlias(true);
    //所画圆的中心 X坐标
    //所画圆的中心 Y坐标
    //所画圆的半径
    //画圆要用的画笔
    //drawCircle(float cx, float cy, float radius, Paint paint)
    canvas.drawCircle(center, center, center - roundWidth / 2, mPaint);
}

(4)半径问题

之前一直觉得如果一个圆的半径是R,画笔的宽度是D,那么这个宽度是圆的半径内还是半径外?

下面展示的结果是,半径内外各一半D/2,所以我们只要用宽度为D的画笔画半径为R-D/2的圆效果就是半径为R的圆

设置的画笔的宽度(setStrokeWidth,这个宽度是半径内一半,半径外一半)





二.drawLine  drawText

public class CanvasView extends View {

    private Paint mPaint;
    private Paint mtextPaint;
    private Context mContext;

    public CanvasView(Context context) {
        super(context);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mPaint = new Paint();
        mContext = context;
        mtextPaint = new Paint();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int roundWidth = dp2px(20);
        float center = getWidth() / 2;
        float lineLength = dp2px(20);

        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(0);

 /**
 * 设置字体参数
 * */

  mtextPaint.setColor(Color.RED);
        mtextPaint.setStyle(Paint.Style.STROKE);
        mtextPaint.setTextSize(dp2px(18));
        mtextPaint.setTypeface(Typeface.DEFAULT_BOLD);
  /**
   * 画线:在view的中心点画个坐标轴
   * */

canvas.translate(getWidth() / 2, getHeight() / 2);

//这时候(0,0)就是center的坐标!!!!!!

 //drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
        canvas.drawLine(0, 0, center + lineLength, 0, mPaint);
        canvas.drawLine(0, 0, 0, center + lineLength, mPaint);

 /**
   * 画出两个字母X,y
   * */

  <span style="white-space:pre">	</span>String strX = "X";
        float strXSize = mtextPaint.measureText(strX);
 //这时候坐标轴中心在这个View的中点
canvas.drawText(strX, center - dp2px(20), -dp2px(10), mtextPaint);

        String strY = "Y";
//        float strXSize = mtextPaint.measureText(strX);
        canvas.drawText(strY, -dp2px(10), center - dp2px(20), mtextPaint);

    }

    public int dp2px(int dp) {
        return (int) (dp * mContext.getResources().getDisplayMetrics().density + 0.5f);
    }
}


(2).drawText产生的文字的问题

public class CanvasView extends View {

    private Paint mPaint;
    private Context mContext;

    public CanvasView(Context context) {
        super(context);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mPaint = new Paint();
        mContext = context;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int TextSize = dp2px(20);
        float center = getWidth() / 2;

        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setTypeface(Typeface.DEFAULT_BOLD);
        mPaint.setTextSize(TextSize);
        //去掉锯齿
        mPaint.setAntiAlias(true);
        String textOne = "one";
        String textTwo = "two";
        float textOneSize = mPaint.measureText(textOne);
        canvas.translate(center, center);
        canvas.drawText(textOne, TextSize / 2, TextSize / 2, mPaint);

        canvas.rotate(90);
        canvas.drawText(textTwo, TextSize / 2, TextSize / 2, mPaint);


    }

    public int dp2px(int dp) {
        return (int) (dp * mContext.getResources().getDisplayMetrics().density + 0.5f);
    }
}


三.drawArc

public class CanvasView extends View {

    private Paint mPaint;
    private Context mContext;

    public CanvasView(Context context) {
        super(context);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mPaint = new Paint();
        mContext = context;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int radius = dp2px(150) / 2;
        int roundWidth = dp2px(20);
        int center = getWidth() / 2;
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(roundWidth);

        //画个弧形
        RectF oval = new RectF(center - radius
                , center - radius
                , center + radius
                , center + radius);
/**
         * drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
         * Draw the specified arc, which will be scaled to fit inside the specified oval.
         * 圆弧是内嵌于这个矩形的
         * */
        //-180开始转    转60度     true(画成扇形)  false只画弧

//-180开始转    转60度     true(画成扇形)  false只画弧
        canvas.drawArc(oval, -180, 60, true, mPaint);
    }

    public int dp2px(int dp) {
        return (int) (dp * mContext.getResources().getDisplayMetrics().density + 0.5f);
    }
}

我觉得最难理解就是这个矩形跟圆的关系,下面就是他们之间的关系!!!

四.CanvasRotate(Canva的旋转)

public class CanvasView extends View {

    private Paint mPaint;
    private Context mContext;

    public CanvasView(Context context) {
        super(context);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mPaint = new Paint();
        mContext = context;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /**
         * 本身矩形框的宽高就是 150dp  150dp
         * */
        //这个就把坐标系的原点改变为当前view的中心点(默认为左上角的顶点)
        //!!!!!!!!!!!!!!!!!!!!!
        canvas.translate(getWidth() / 2, getHeight() / 2);
        /**
         * 画一个蓝色的矩形
         * */
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Paint.Style.STROKE);

  //先画蓝色矩形

canvas.drawRect(dp2px(0), dp2px(0), dp2px(70), dp2px(50), mPaint);

        /**
         * 画一个红色的矩形
         * */
        //旋转画布
        canvas.rotate(90);
        //再画红色矩形
        mPaint.setColor(Color.RED);
        canvas.drawRect(dp2px(0), dp2px(0), dp2px(70), dp2px(50), mPaint);

        /**
         *
         * 可以看出画布的坐标被移动的90度,画布没有动!!!!!!!
         * */
    }

    public int dp2px(int dp) {
        return (int) (dp * 	mContext.getResources().getDisplayMetrics().density + 0.5f);
    }
}
可以看出画布的坐标被移动的90度,画布没有动!!!!!!!

画布的坐标被转了90度,画布本身没有转


五.Canvas Save Rotate(Canva的旋转和Save)

canvasRotate  canvas转动  然后只是坐标变了

如果调用restore次数多于save就会报错!!!!

public class CanvasView extends View {

    private Paint mPaint;
    private Context mContext;
    private Paint mTextPaint;
    /**
     * 圆环中间百分号颜色
     */
    private int percentColor;

    /**
     * 圆环中间百分号尺寸
     */
    private int percentSize;

    public CanvasView(Context context) {
        super(context);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mPaint = new Paint();
        mTextPaint = new Paint();
        mContext = context;
        // “%”符号颜色、尺寸
        percentColor = Color.parseColor("#ff0000");
        percentSize = (int) dp2px(20);
    }

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

        mTextPaint.setStrokeWidth(0);
        mTextPaint.setColor(percentColor);
        mTextPaint.setTextSize(percentSize);
        mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);


        // 矩形宽度
        int lenght = dp2px(50);
        /**
         * 坐标系原点变成了View的原点,不再是默认的View左上角
         *
         * */
        canvas.translate(getWidth() / 2, getHeight() / 2);
        // 第一个黑色矩形
        canvas.drawRect(-lenght, -lenght, lenght, lenght, mPaint);
        // 保存x轴方向为3点钟方向的坐标
        canvas.save();
        /**
         * 旋转坐标轴
         * 坐标系顺时针转了45度
         * */
        canvas.rotate(45);
        mPaint.setColor(Color.BLUE);
        // 第二个蓝色矩形
        canvas.drawRect(-lenght, -lenght, lenght, lenght, mPaint);
        /**
         * 恢复坐标轴(刚才偏移了45度),变成了x水平
         * */
        canvas.restore();
        mPaint.setColor(Color.RED);
        // 绘制坐标轴
        canvas.drawLine(0, 0, 300, 0, mPaint);
        canvas.drawText("x", dp2px(50), 0, mTextPaint);
        canvas.drawLine(0, 0, 0, 300, mPaint);
        canvas.drawText("y", 0, dp2px(50), mTextPaint);
    }

    public int dp2px(int dp) {
        return (int) (dp * mContext.getResources().getDisplayMetrics().density + 0.5f);
    }
}


六.drawOval (画一个渐变色的圆,oval其实是椭圆的意思)

public class ZhiMaView extends View {
    private Context mContext;
    private final int[] mColors = new int[]{0xffff0000, 0xffffff00, 0xff00ff00,
            0xff00ffff, 0xff0000ff, 0xffff00ff};// 渐变色环颜色
    private Paint mPaint;

    public ZhiMaView(Context context) {
        super(context);
        init(context);
    }

    public ZhiMaView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ZhiMaView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        this.mContext = context;
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int CENTER_X = getWidth() / 2;
/**
 *  public SweepGradient (float cx, float cy, int[] colors, float[] positions)
 Added in API level 1

 A subclass of Shader that draws a sweep gradient around a center point.
 Parameters
 cx    The x-coordinate of the center
 cy    The y-coordinate of the center
 colors    The colors to be distributed between around the center.
 There must be at least 2 colors in the array.
 positions     May be NULL. The relative position of each corresponding color in the colors array,
 beginning with 0 and ending with 1.0. If the values are not monotonic,
 the drawing may produce unexpected results.
 If positions is NULL, then the colors are automatically spaced evenly.
 *
 * */
        //不太理解这个//围绕着一个中心点用着色器画渐变色
        //A subclass of Shader that draws a sweep gradient around a center point.
        Shader s = new SweepGradient(0, 0, mColors, null);
        mPaint.setShader(s);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(40);
        float r = CENTER_X - mPaint.getStrokeWidth() / 2;
        canvas.save();
        canvas.translate(CENTER_X, CENTER_X);// 移动中心
        //canvas.rotate(150);
        canvas.drawOval(new RectF(-r, -r, r, r), mPaint);// 画出色环和中心园
        canvas.restore();
    }
}

七.DrawBitmap

public class BitmapView extends View {

    private Bitmap bitmap;
    private Paint bitmapPaint= new Paint();

    public BitmapView(Context context) {
        super(context);
        init();
    }

    public BitmapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public BitmapView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.home_my_try_click);
        bitmapPaint.setAntiAlias(true);
        bitmapPaint.setColor(Color.BLACK);
        bitmapPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(bitmap,0,0,bitmapPaint);
    }
}

//布局文件activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context=".MainActivity">

            <com.weixin.drawbitmap.view.BitmapView
                android:layout_width="300dp"
                android:layout_height="300dp"/>
</RelativeLayout>


这里设置是从0,0开始画

这个时候这个viewcenter in Parent ,也是从(0,0)这个时候这个0,0是相对他的容器



(1)setTranslatepreTranslate还有postTranslate 之间的区别

<1>setTranslate

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Matrix matrix=new Matrix();
    /**
     *  matrix.setScale(interpolatedTime, interpolatedTime);
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
        经常在中心缩放的应用中看到这段代码.
        preTranslate是指在setScale前,平移,postTranslate是指在setScale后平移
        注意他们参数是平移的距离,而不是平移目的地的坐标!!!!!
        由于缩放是以(0,0)为中心的,所以为了把界面的中心与(0,0)对齐,就要preTranslate(-centerX, -centerY),
        setScale完成后,调用postTranslate(centerX, centerY),再把图片移回来,这样看到的动画效果就是activity的界面图片从中心不停的缩放了

         注:centerX和centerY是界面中心的坐标
         因为矩阵变换设计到合并矩阵的情况,所以才分了pre和post函数,可以参照skia库中SkMatrix.cpp函数原型。pre表示回受到先前的变换的影响,而post不会。比如
         (1)
         matrxi.scale(0.5, 0.5);
         matrix.preTranslate(100, 0);
         (2)
         matrix.scale(0.5, 0.5);
         matrix.postTranslate(100, 0);
         第一段代码缩放后会再平移100*0.5=50的距离,而第二段代码缩放后会平移坐标给定的100的距离。
     *
     * */
    matrix.postScale(0.5f, 0.5f);
matrix.preTranslate(240,0); //实际移动的距离是120 = 240 * 0.5f;
    canvas.drawBitmap(bitmap,matrix,bitmapPaint);
}

<2>preTranslate

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Matrix matrix=new Matrix();
    matrix.postScale(0.5f, 0.5f);
matrix.postTranslate(120,0); 
    canvas.drawBitmap(bitmap,matrix,bitmapPaint);
}

<1>和<2>的效果都是一样的如下图






八.DrawClock()画一个钟(一个简单的实践)

public class ClockView extends View {
    private Context mContext;
    private Paint mPaint;
    private Paint mTextPaint;

    public ClockView(Context context) {
        super(context);
        init(context);
    }

    public ClockView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ClockView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        mPaint = new Paint();
        mTextPaint = new Paint();
    }

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

        /**
         * 先画一个大圆,默认坐标系原点是View的左上角
         * */
        int center = getWidth() / 2;
        int roundWidth = dp2px(10);
        int radius = getWidth() / 2 - dp2px(100) / 2 - roundWidth / 2;
        int textWidth = dp2px(10);
        //去掉锯齿
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(roundWidth);
        canvas.drawCircle(center, center, radius, mPaint);


        /**
         *画刻度还有数字
         * */
        //刻度线不要那么宽
        mPaint.setStrokeWidth(0);
        //刻度线换一种颜色
        // mPaint.setColor(Color.BLACK);


        mTextPaint.setStrokeWidth(0);
        mTextPaint.setColor(Color.RED);
        mTextPaint.setTextSize(textWidth);
        mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);

        canvas.translate(center, center);
        //这时候坐标系  X轴在三点钟方向 Y轴在六点钟方向
        canvas.save();
        //坐标系原点从原来的View的左上角顶点移到View的中心

        //从刻度1开始画(坐标轴逆时针转60)
        canvas.rotate(-60);

        for (int i = 0; i < 60; i++) {

            if (i % 5 == 0) {
                //每五个小格就是一个大格,所以画长刻度
                canvas.drawLine(radius, 0, radius + dp2px(25), 0, mPaint);
                //这时候坐标系 X轴在一点钟方向  Y轴在4点钟方向
                //这个save保存了每一小格转了6度
                canvas.save();
                //画完大刻度就把大刻度的数字标一下(这里需要注意一下,需要数字朝向View的中心)
                //开始移动坐标系到接近数字的地方
                canvas.translate(radius + dp2px(30), 0);
                //为了让数字的底部对着View的中心,所以canvas要顺时针转90度
                canvas.rotate(90);
                String str = String.valueOf(i / 5 + 1);
                float strSize = mPaint.measureText(str);
                canvas.drawText(str, -strSize / 2, 0, mTextPaint);
                //回到//这时候坐标系 X轴在一点钟方向  Y轴在4点钟方向
                canvas.restore();

            } else {
                //其他的情况下就是一个小格,所以画短刻度
                canvas.drawLine(radius, 0, radius + dp2px(15), 0, mPaint);
            }

            //每画完一次刻度就顺时针转6度(也就是下一个刻度)
            canvas.rotate(360 / 60f);
        }
        //这时候坐标系  X轴在三点钟方向 Y轴在六点钟方向
        canvas.restore();
        //箭头和线的颜色换成红色
        mPaint.setColor(Color.RED);
        //现在开始画箭头底下的线
        canvas.drawLine(0, 0, 0, -radius + dp2px(3), mPaint);
        Path path = new Path();
        //画箭头
        path.moveTo(-dp2px(3), -radius);//三角形左下角顶点
        path.lineTo(dp2px(3), -radius);//三角形右下角顶点
        path.lineTo(0, -radius - dp2px(3)); //顶点
        path.close();
        canvas.drawPath(path, mPaint);

        //写文字
        String MyText = "MyCanvasClock";
        float MyTextSize = mTextPaint.measureText(MyText);
        canvas.drawText(MyText, -MyTextSize / 2, dp2px(30), mTextPaint);

    }

    public int dp2px(int dp) {
        return (int) (dp * mContext.getResources().getDisplayMetrics().density + 0.5f);
    }
}


九.做个类似于芝麻信用分的实践

//步骤在代码中写(除了画等级分数之类,这个简单,可以参考上面的画钟)

public class MyView extends View {
    //外围圆
    private Paint outSideCirlePaint = new Paint();
    //去掉下面的120
    private Paint arc120Paint = new Paint();
    //画大刻度的画笔
    private Paint BigScalePaint = new Paint();
    //画小刻度的画笔
    private Paint smallScalePaint = new Paint();
    //画中间的分数和信用等级
    private Paint textPaint = new Paint();
    //画进度条
    private Paint processPaintBackGroud = new Paint();
    private Paint processPaint = new Paint();
    //画图片
    private Paint bitmapPaint = new Paint();
    private int viewWidth;
    private int viewHeight;
    private Context mContext;
    private int outSideCriclePaintWidth;
    private int innerSideCriclePaintWidth;
    private int mCenterX;
    private int mCenterY;
    private int mRadius;
    private String creditRand;
    private float  creditScore;
    private Bitmap bitmapArrow;
    private int mInnerSideRadius;
    private float totalRotateAngle;
    private boolean rotating = false;
    private float rotateAngle;
    private float currentAngle;

    public interface setRotateAnlgleListener {
        void setRotateAngle(int rotateAngle);
    }

    public MyView(Context context) {
        super(context);
        this.mContext = context;
        init();
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        init();
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        init();
    }

    private void init() {
        initData();
        initPaint();

    }

    private void initData() {

        //最外面圆画笔的宽度
        outSideCriclePaintWidth = CommonUtils.Dp2Px(mContext, 10);
        innerSideCriclePaintWidth = CommonUtils.Dp2Px(mContext, 5);
        //信用等级
        creditRand = "信用等级";
        //信用分数
        creditScore = 350;
    }

    private void initPaint() {
        //在外面的大圆画笔的设置
        outSideCirlePaint.setAntiAlias(true);
        outSideCirlePaint.setColor(Color.parseColor("#E0E0E0"));
        outSideCirlePaint.setStrokeWidth(outSideCriclePaintWidth);
        outSideCirlePaint.setStyle(Paint.Style.STROKE);
        outSideCirlePaint.setAlpha(50);

        //设置圆正下方152度去掉圆弧的画笔
        arc120Paint.setAntiAlias(true);
        arc120Paint.setColor(Color.parseColor("#9393FF"));
        arc120Paint.setStyle(Paint.Style.FILL_AND_STROKE);

        //初始化画大刻度的画笔
        BigScalePaint.setAntiAlias(true);
        BigScalePaint.setColor(Color.parseColor("#000000"));
        BigScalePaint.setStyle(Paint.Style.STROKE);
        BigScalePaint.setStrokeWidth(CommonUtils.Dp2Px(mContext, 2));

        //初始化画小刻度的画笔
        smallScalePaint.setAntiAlias(true);
        smallScalePaint.setColor(Color.parseColor("#000000"));
        smallScalePaint.setStyle(Paint.Style.STROKE);
        smallScalePaint.setStrokeWidth(CommonUtils.Dp2Px(mContext, 1));

        //初始化画字的画笔
        textPaint.setAntiAlias(true);
        textPaint.setColor(Color.parseColor("#ffffff"));
        textPaint.setStyle(Paint.Style.STROKE);
        textPaint.setTextSize(CommonUtils.Dp2Px(mContext, 20));

        //进度条的画笔
        processPaint.setAntiAlias(true);
        processPaint.setColor(Color.parseColor("#00ff00"));
        processPaint.setStyle(Paint.Style.STROKE);
        processPaint.setStrokeWidth(innerSideCriclePaintWidth);

        processPaintBackGroud.setAntiAlias(true);
        processPaintBackGroud.setColor(Color.parseColor("#4DFFFF"));
        processPaintBackGroud.setStyle(Paint.Style.STROKE);
        processPaintBackGroud.setStrokeWidth(innerSideCriclePaintWidth);

        //图片
        bitmapPaint.setAntiAlias(true);

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //获取中心
        mCenterX = getWidth() / 2;
        mCenterY = getHeight() / 2;

        mRadius = mCenterX - outSideCriclePaintWidth / 2;
        //1.画出最外面的大圆
        canvas.drawCircle(mCenterX, mCenterY, mRadius, outSideCirlePaint);

        //2.把中心的移到view的中心
        canvas.translate(mCenterX, mCenterY);

        //3.然后画刻度 大的  小的(总共30个空格,240度,一格是八度,6格是一个大刻度)
        //从右画到左
        //(1)先把canvas先逆时针转 60
        for (int i = 0; i < 31; i++) {
            canvas.save();
            canvas.rotate(-(60 + i * 8), 0, 0);
            if (0 == i % 6) {
                //6个空格画个大刻度
                canvas.drawLine(0, mCenterX, 0, mRadius - CommonUtils.Dp2Px(mContext, 10), BigScalePaint);
            } else {
                //画个小刻度
                canvas.drawLine(0, mCenterX, 0, mRadius - CommonUtils.Dp2Px(mContext, 5), smallScalePaint);
            }
            //还原到最开始的地方
            //也就是坐标中心在view中心的时候  x  y 水平竖直
            canvas.restore();
        }


        //6.画信用等级

        //7.画进度条//此时坐标轴的原点就在view中心
        mInnerSideRadius = mCenterX - CommonUtils.Dp2Px(mContext, 20);
        //进度条的背景
        canvas.drawCircle(0, 0, mInnerSideRadius, processPaintBackGroud);
        //进度条
        RectF rectF = new RectF(-mInnerSideRadius, -mInnerSideRadius, mInnerSideRadius, mInnerSideRadius);
        //-210 startAngle  120 sweepAngle
        canvas.drawArc(rectF, -210, currentAngle, false, processPaint);

        //8.去掉正下方的240度的圆弧
        //现在view的中心的是(0,0)
        clear120Arc(0, 0, canvas);

        canvas.save();
        //9.画出图片
        bitmapArrow = BitmapFactory.decodeResource(getResources(), R.drawable.arrow);
        canvas.rotate(-30+currentAngle);
        Matrix matrix = new Matrix();
        int bitmapWidth = bitmapArrow.getWidth();
        int bitmapHeight = bitmapArrow.getHeight();
        //这时候坐标系  已经逆时针偏转30度
        matrix.preTranslate(-mInnerSideRadius - bitmapWidth * 3 / 8, -bitmapHeight / 2);
        canvas.drawBitmap(bitmapArrow, matrix, bitmapPaint);

        canvas.restore();
        //4.画中间的字
        float creditTextWidth = textPaint.measureText(creditRand);
        canvas.drawText(creditRand, -creditTextWidth / 2, CommonUtils.Dp2Px(mContext, 50), textPaint);

        //5.画中间的分数
        float creditScoreWidth = textPaint.measureText(String.valueOf((int)creditScore));
        canvas.drawText(String.valueOf((int)creditScore), -creditScoreWidth / 2, CommonUtils.Dp2Px(mContext, 30), textPaint);
    }

    /**
     * 清除下面的120度的圆弧
     */
    private void clear120Arc(int screenWithCenter, int screenHeighWidth, Canvas canvas) {
        Point pointLeftBotton = new Point();
        //设置左下角的点
        pointLeftBotton.set(screenWithCenter - viewWidth / 2, screenHeighWidth + (int) ((viewWidth / 2) * Math.tan((Math.PI / 180) * 30)));
        Point pointRightBotton = new Point();
        //设置右下角的点
        pointRightBotton.set(screenWithCenter + viewWidth / 2, screenHeighWidth + (int) ((viewWidth / 2) * Math.tan((Math.PI / 180) * 30)));

        Path path = new Path();
//        path.reset();
        path.moveTo(screenWithCenter, screenHeighWidth);
        path.lineTo(pointLeftBotton.x, pointLeftBotton.y);
        path.lineTo(pointLeftBotton.x, screenHeighWidth + viewHeight / 2);
        path.lineTo(pointRightBotton.x, screenHeighWidth + viewHeight / 2);
        path.lineTo(pointRightBotton.x, pointRightBotton.y);
        path.close();
        System.out.println("xcqw screentWidthCenter-" + screenWithCenter + "-screenHeighWidth-" + screenHeighWidth);
        System.out.println("xcqw pointLeftBotton-" + pointLeftBotton.x + "-pointLeftBotton.y-" + pointLeftBotton.y);
        System.out.println("xcqw pointRightBotton-" + pointRightBotton.x + "-pointRightBotton.y-" + pointRightBotton.y);
        canvas.drawPath(path, arc120Paint);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //获取view的宽度,高度
        viewWidth = w;
        viewHeight = h;
        System.out.println("xcqw viewWidth-" + viewWidth + "-viewHeight-" + viewHeight);
    }

    public void setRotateAngle(int outcreditScore) {
        System.out.println("xcqw setRotateAngle");
//                if ( creditScore <= 350 ) {
//                    totalRotateAngle = 0f;
//                } else if ( creditScore <= 550 ) {
//                    totalRotateAngle = ( creditScore - 150 ) * 80 / 400f ;
//                } else if ( creditScore <= 700 ) {
//                    totalRotateAngle = ( creditScore - 550 ) * 120 / 150f + 80 ;
//                } else if ( creditScore <= 950 ) {
//                    totalRotateAngle = ( creditScore - 700 ) * 40 / 250f + 200;
//                } else {
//                    totalRotateAngle = 240f ;
//                }
        if (outcreditScore <= 350) {
            totalRotateAngle = 0f;
        } else if (outcreditScore <= 950) {
            //总共240度  量程是350- 950分
            totalRotateAngle = (outcreditScore - 350)/(600 / 240);
        } else {
            totalRotateAngle = 240f;
        }
        rotateAngle = totalRotateAngle / 60;
        currentAngle = 0;
        new Thread(new Runnable() {
            @Override
            public void run() {
                rotating = true;
                while (rotating) {
                    //箭头正在旋转
                    currentAngle += rotateAngle;
                    creditScore = (600/240)*currentAngle+350;
                    SystemClock.sleep(50);

                    if (currentAngle >= totalRotateAngle) {
                        currentAngle = totalRotateAngle;
                        rotating = false;
                    }

                    if (currentAngle >= 0 && currentAngle < 91) {
                        creditRand = "信用较差";
                    } else if (currentAngle > 90 && currentAngle < 151) {
                        creditRand = "信用良好";
                    } else if (currentAngle > 150) {
                        creditRand = "信用优秀";
                    }
                    postInvalidate();
                }
            }
        }).start();
    }
}
源码在这里


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值