Android图形绘制-Canvas高级使用

标签: AndroidUI  android  canvas

坐标体系

在这里插入图片描述

在这里插入图片描述

        /**
         * 1、坐标的平移
         * 2、特性就是在修改坐标后,这个过程中是不可逆的
         */
        RectF r = new RectF(0, 0, 400, 400);
        canvas.drawRect(r, mPaint);
   
        canvas.translate(100, 100);
        
        mPaint.setColor(Color.BLUE);
        RectF r2 = new RectF(-100, -100, 400, 400);
        canvas.drawRect(r2, mPaint);

        mPaint.setColor(Color.YELLOW);
        canvas.drawRect(new RectF(0, 0, 400, 400), mPaint);

在这里插入图片描述

Matrix变换矩阵

        Matrix matrix0 = canvas.getMatrix();
        Log.i(TAG, matrix0.toString());

输出:

Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}

调用translate和rotate方法后打印Matrix:

        //默认有一个绘图坐标系
        RectF r = new RectF(0, 0, 400, 400);
        canvas.drawRect(r, mPaint);
        Matrix matrix = canvas.getMatrix();
        Log.i(TAG, matrix.toString());

        canvas.translate(100, 200);
        
        mPaint.setColor(Color.BLUE);
        RectF r2 = new RectF(0, 0, 400, 400);
        canvas.drawRect(r2, mPaint);
        Matrix matrix1 = canvas.getMatrix();
        Log.i(TAG, matrix1.toString());
        
        canvas.rotate(30,200,200);
        
        mPaint.setColor(Color.YELLOW);
        canvas.drawRect(new RectF(0, 0, 400, 400), mPaint);
        Matrix matrix2 = canvas.getMatrix();
        Log.i(TAG, matrix2.toString());

显示效果如下:
在这里插入图片描述
输出结果如下:

Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
Matrix{[1.0, 0.0, 100.0][0.0, 1.0, 200.0][0.0, 0.0, 1.0]}
Matrix{[0.8660254, -0.5, 226.79492][0.5, 0.8660254, 126.79492][0.0, 0.0, 1.0]}

WatchView

public class WatchView extends View {
    private static final String TAG = "WatchView";
    private int mWidth;
    private int mHerght;


    public WatchView(Context context) {
        super(context);
    }

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

    public WatchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth();
        mHerght = getMeasuredHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画外圆
        Paint paintCircle = new Paint();
        paintCircle.setStrokeWidth(5);
        paintCircle.setAntiAlias(true);
        paintCircle.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(mWidth / 2,
                mHerght / 2, mWidth / 2, paintCircle);

        //画刻度线
        Paint paintDegree = new Paint();
        paintCircle.setStrokeWidth(3);
        for (int i = 0; i < 12; i++) {
            if (i == 0 || i == 3 || i == 6 || i == 9) {
                paintDegree.setStrokeWidth(5);
                paintDegree.setTextSize(100);
                canvas.drawLine(mWidth / 2, mHerght / 2 - mWidth / 2,
                        mWidth / 2, mHerght / 2 - mWidth / 2 + 60,
                        paintDegree);
                String degree = String.valueOf(i);
                canvas.drawText(degree, mWidth / 2 - paintDegree.measureText(degree) / 2,
                        mHerght / 2 - mWidth / 2 + 160, paintDegree);
            } else {
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(50);
                canvas.drawLine(mWidth / 2, mHerght / 2 - mWidth / 2,
                        mWidth / 2, mHerght / 2 - mWidth / 2 + 30,
                        paintDegree);
                String degree = String.valueOf(i);
                canvas.drawText(degree, mWidth / 2 - paintDegree.measureText(degree) / 2,
                        mHerght / 2 - mWidth / 2 + 60, paintDegree);
            }
            canvas.rotate(30, mWidth / 2, mHerght / 2);
        }
        //画指针
        Paint paintHour = new Paint();
        paintHour.setStrokeWidth(20);
        Paint paintMinute = new Paint();
        paintMinute.setStrokeWidth(10);
//        Log.i(TAG, "Current SaveCount1 = " + canvas.getSaveCount());
//        canvas.save();
//        Log.i(TAG, "Current SaveCount2 = " + canvas.getSaveCount());
        canvas.translate(mWidth/2, mHerght/2);
        canvas.drawLine(0,0,100,100,paintHour);
        canvas.drawLine(0,0,100,200,paintMinute);
//        canvas.restore();
        Log.i(TAG, "Current SaveCount3 = " + canvas.getSaveCount());
    }
}

在这里插入图片描述


图层

状态栈

save、 restore方法来保存和还原变换操作Matrix以及Clip剪裁,也可以通过restoreToCount直接还原到对应栈的保存状态

在这里插入图片描述

Layer栈

saveLayer的时候都会新建一个透明的图层(离屏Bitmap-离屏缓冲),并且会将saveLayer之前的一些Canvas操作延续过来, 后续的绘图操作都在新建的layer上面进行,当我们调用restore 或者 restoreToCount 时 更新到对应的图层和画布上

在这里插入图片描述

public class MyView extends View {


    private static final String TAG = "MyView";

    private Paint mPaint = null;
    private Bitmap mBitmap = null;

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

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lsj);
        init();
    }

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

    private void init() {
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(10);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        //第1次保存,并通过canvas.getSaveCount的到当前状态栈容量
        canvas.save();
        Log.i(TAG, "Current SaveCount1 = " + canvas.getSaveCount());

        canvas.translate(400, 400);
        RectF rectF = new RectF(0, 0, 600, 600);


        canvas.drawBitmap(mBitmap, null, rectF, mPaint);  //2
        //第2次保存,并通过canvas.getSaveCount的到当前状态栈容量

        Log.i(TAG, "Current SaveCount2 = " + canvas.getSaveCount());

        canvas.rotate(45);

        canvas.drawBitmap(mBitmap, null, rectF, mPaint);  //3
        //第3次保存,并通过canvas.getSaveCount的到当前状态栈容量
        canvas.save();
        mPaint.setColor(Color.YELLOW);
        canvas.drawRect(new RectF(0, 0, 400, 400), mPaint);
        Log.i(TAG, "Current SaveCount3 = " + canvas.getSaveCount());
        canvas.restoreToCount(1);
        Log.i(TAG, "Current SaveCount4 = " + canvas.getSaveCount());//2

//        canvas.rotate(45);
//
//        canvas.drawBitmap(mBitmap, null, rectF, mPaint);
//        //第4次保存,并通过canvas.getSaveCount的到当前状态栈容量
//        canvas.save();
//        Log.i(TAG, "Current SaveCount4 = " + canvas.getSaveCount());
//        //通过canvas.restoreToCount出栈到第三层状态
//        canvas.restoreToCount(1);//出栈到指定层
//        Log.i(TAG, "restoreToCount--Current SaveCount = " + canvas.getSaveCount());
//
//        canvas.translate(0, 200);
//
//        //rectF = new RectF(0,0,600,600);
//        canvas.drawBitmap(mBitmap, null, rectF, mPaint);
//        //通过canvas.restoreToCount出栈到第1层(最原始的那一层)状态
//        canvas.restoreToCount(3);
//        Log.i(TAG, "restoreToCount--Current SaveCount = " + canvas.getSaveCount());
//        canvas.drawBitmap(mBitmap, null, rectF, mPaint);
    }
}

在这里插入图片描述

版权声明:本文为hongxue8888原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hongxue8888/article/details/103957171