Android高级UI开发(四十三)Canvas基本知识(1)

本文深入讲解了Android中Canvas绘图的基本原理与高级技巧,包括直线、多边形、圆形、椭圆、贝塞尔曲线的绘制,以及平移、旋转、缩放、剪裁等图形变换操作。同时,文章还探讨了Canvas的状态保存与Layer栈的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 直接贴代码,注释很详细。源码下载:https://download.csdn.net/download/gaoxiaoweiandy/12371948

package com.xiaowei.lsn7_canvas;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;
import com.xiaowei.lsn7_canvas.R;

/**
 * Created by John on 2017/5/14.
 */

public class MyView2 extends View {
    private Bitmap mBitmap;
    public MyView2(Context context) {
        this(context,null);
    }

    public MyView2(Context context, AttributeSet attrs) {
        super(context, attrs);
        mBitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.xyjy2)).getBitmap();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制直线
        Paint paint = new Paint();
        paint.setColor(Color.RED);
		//paint.setStyle(Paint.Style.FILL);//
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(20);

        /*gxw-s for 画线段2点之间
		    canvas.drawLine(0, 0, 100, 100, paint);
		gxw-e*/


        /*gxw-s for 画多段线段,4个值为1条线段,4个值分别是起点的x,y与终点的x',y'。
            float []pts = {0,0,100,100,200,200,300,300,0,0};
            canvas.drawLines(pts, paint);
		gxw-e*/

        /*gxw-s for  画多段线段,可以跳过几个值(这里为6),跳过之后再去绘制几个值(这里为4,即(300,300,0,0)),最终就只画了这条起点为300,300终点为0,0的线段
            float []pts = {0,0,100,100,200,200,300,300,0,0,100,100};
            canvas.drawLines(pts, 6, 4, paint);
		gxw-e*/


        /*gxw-s for 画1个点与画多个点
            canvas.drawPoint(500, 500, paint);
            float []pts = {0,0,100,100,200,200,300,300,0,0};
            canvas.drawPoints(pts, paint);
        gxw-e */


        /*gxw-s for 画矩形
            RectF r = new RectF(100, 100, 500, 500);
            canvas.drawRect(r, paint);
            canvas.drawRect(100, 100, 400, 500, paint);
        gxw-e*/


        /*gxw-s for 绘制圆角矩形,30,30为圆角半径,x,y
            RectF r = new RectF(100, 100, 400, 500);
            canvas.drawRoundRect(r, 30, 30, paint);
        gxw-e*/

        //画圆canvas.drawCircle(300, 300, 200, paint);

        /*gxw-s for 绘制椭圆的2种方法
            // canvas.drawOval(100,100,400,300, paint);
            RectF r = new RectF(100, 100, 400, 300);
            canvas.drawOval(r, paint);
        gxw-e*/

        /*gxw-s for 画弧形
            // paint.setStyle(Paint.Style.FILL);
            RectF r = new RectF(100, 100, 400, 500);
            canvas.drawArc(r, 0, 90, false, paint);//顺时针旋转90度
        gxw-e */


        /*gxw-s for 绘制路径,这里为直线路径与贝塞尔曲线*/

            /*	绘制直线路径
                Path path = new Path();
                path.moveTo(100, 100);//画笔落笔的位置
                path.lineTo(200, 100);
                path.lineTo(200, 200);
                path.close();//封闭路径,在这里如果不封闭,绘制的将是一个直角,不能成为一个三角形。
             */

            /*  gxw-s for 绘制贝塞尔曲线路径
                Path path = new Path();
                path.cubicTo(250, 200, 350, 300, 450, 400);//绘制贝塞尔曲线
                canvas.drawPath(path, paint);gxw-e for 绘制贝塞尔曲线路径*/
        /*gxw-e */


        /*gxw-s for 圆角矩形路径
            RectF r = new RectF(100, 100, 600, 800);
            Path path = new Path();
            float radii[] = {10,10,10,10,10,10,50,60};  //圆角半径,分别为左上,右上,右下,左下。
            path.addRoundRect(r, radii, Path.Direction.CCW);
            canvas.drawPath(path, paint);
        gxw-e */


        /*gxw-s for 区域:将椭圆绘制成多个小矩形组成,高等数学中的微积分
            RectF r = new RectF(100, 100, 600, 800);
            Path path = new Path();
            path.addOval(r, Path.Direction.CCW);

            //创建一块矩形的区域
            Region region = new Region(100, 100, 600, 800);
            Region region1 = new Region();
            region1.setPath(path, region);//path的椭圆区域和矩形区域进行交集

            //结合区域迭代器使用(得到图形里面的所有的矩形区域)
            RegionIterator iterator = new RegionIterator(region1);

            Rect rect = new Rect();
            while (iterator.next(rect)) {
                canvas.drawRect(rect, paint);
            }
            还有区域的合并,交集等操作。
        gxw-e */


     /*
           平移START
            Canvas绘制坐标轴,canvas的坐标系原点永远是View的左上角
            canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴
            paint.setColor(Color.BLUE);
            canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴


            //这里实质平移的是Canvas里面的图形(绘图坐标系),然后Canvas并没有平移,它的坐标系原点还是View的左上角。
            canvas.translate(100, 50);

            canvas.save();

            //Canvas平移后再绘制坐标轴,发现“坐标轴图形”确实平移了
            paint.setColor(Color.GREEN);
            //canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴
            paint.setColor(Color.BLACK);
            canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴
            ===================================================================

            //旋转
            canvas.rotate(45);
            canvas.save();
            //旋转后再绘制坐标轴,发现“坐标轴图形”确实旋转了
            paint.setColor(Color.GREEN);
            canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴
            paint.setColor(Color.BLACK);
            canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴
            ==================================================================


           //缩放Scale
            canvas.restoreToCount(1);//还原到第一次save的 状态
            canvas.drawColor(Color.BLUE);
            RectF r = new RectF(0, 0, 400, 400);
            paint.setColor(Color.RED);
            //sx,sy:分别对x/y方向的一个缩放系数,画布的缩放会导致里面所有的绘制的东西都会有一个缩放效果
            canvas.scale(1.5f, 1.5f);
            canvas.drawRect(r, paint);
           =====================================================================

             //旋转角度
            canvas.restoreToCount(1);//还原到第一次save的 状态
            canvas.drawColor(Color.BLUE);
            paint.setColor(Color.WHITE);
            RectF rect = new RectF(300, 600, 400, 800);
            canvas.drawRect(rect, paint);
            canvas.rotate(40, 300, 600);
            paint.setColor(Color.YELLOW);
            canvas.drawRect(rect, paint);
	      =============================================================================
		    */



		//4. 斜拉画布
        /*  canvas.drawColor(Color.BLUE);
            paint.setColor(Color.RED);
            RectF rec2t = new RectF(100, 100, 300, 300);
            canvas.drawRect(rec2t, paint);
            paint.setColor(Color.YELLOW);
            //sx,sy倾斜度:X轴方向上倾斜60度,tan60=根号3
            canvas.skew(1.73f, 0);
            canvas.drawRect(rec2t, paint);
            =========================================================================
            */


        /*gxw-s for 裁剪
            RectF r = new RectF(200, 200, 400, 500);
            canvas.drawRect(r, paint);
            paint.setColor(Color.BLUE);
            canvas.clipRect(new Rect(250, 250, 300, 400));
            canvas.drawColor(Color.YELLOW);
            =====================================================
         gxw-e for 裁剪*/

        canvas.drawColor(Color.WHITE);
        paint.setColor(Color.GREEN);
        RectF r = new RectF(200, 200, 400, 500);
        canvas.drawRect(r, paint);
        canvas.translate(100,100);
        paint.setColor(Color.RED);
        canvas.drawRect(r, paint);

        int layer = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
        paint.setColor(Color.YELLOW);
        canvas.drawRect(r, paint);
        /*gxw -s for 笔记
        Canvas的状态保存---状态栈、Layer栈
        状态栈--save、 restore方法来保存和还原变换操作Matrix以及Clip剪裁,也可以通过restoretoCount直接还原到对应栈的保存状态
        Layer栈--- saveLayer的时候都会新建一个透明的图层(离屏Bitmap-离屏缓冲),并且会将saveLayer之前的一些Canvas操作延续过来
                后续的绘图操作都在新建的layer上面进行,当我们调用restore 或者 restoreToCount 时 更新到对应的图层和画布上
         */
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冉航--小虾米

希望得到您的鼓励和交流

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值