前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android关于Canvas你所知道的和不知道的一切

Android关于Canvas你所知道的和不知道的一切

作者头像
张风捷特烈
发布2018-12-06 11:45:35
3.3K0
发布2018-12-06 11:45:35
举报
文章被收录于专栏:Android知识点总结

在一年的Android自学中,Canvas一直是我能避且避的类,甚至不惜封装自己的绘图库来替代它。 如今回首,虐我千万次的Canvas也不过如此,静下心看看,其实也没有想象中的那么糟糕。 就像曾经等级30的我去打点等级40的副本(Canvas)非常吃力,现在等级50的我回来吊打它一样。 所以朋友,遇到承受不了的困扰,不要太沮丧,去别的地方刷怪升级,一旦境界提升了,早晚可以"报仇雪恨" Android技术栈C模块,第一篇正式开讲:

如果将View、Canvas、Paint、Coder(编写代码的人)做个类比:

那么Canvas是一个黑匣子里的白纸,它的特性是可以添加图层和平移,旋转、缩放、斜切等,最重要的就是它的n种drawXXX... Paint是绘制用的画笔,它的特性是提供绘制工具与制定画笔的特殊效果(如笔头Cap,线接方式Join,六种Effect) View则是让黑匣子变成透明的视口,也是我们最熟悉。那Coder就是在操纵画笔的在白纸上绘制的人,是最核心的


一、前期准备:

1.自定义View中的canvas:

说起Canvas对象,貌似很少去new它,更多的是在自定义控件时的Ondraw方法里回调有canvas对象

代码语言:javascript
复制
public class CanvasView extends View {

    public CanvasView(Context context) {
        this(context, null);

    }

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

    private void init() {
        //TODO init 初始化
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //TODO drawGrid 绘制网格
        //TODO drawCoo 绘制坐标系
    }
}

这里值得提一下:onDarw中尽量不要创建对象,因为视图更新都会走onDarw(),而不断开辟空间

onDraw.png


2.准备网格与坐标系

如果要演示绘制,这两者必不可少,放在analyze包里 实现效果:给出坐标原点后会自动绘制坐标系以及网格和数字

网格和坐标系效果2.png

1).使用方式:
代码语言:javascript
复制
//成员变量
    private Paint mGridPaint;//网格画笔
    private Point mWinSize;//屏幕尺寸
    private Point mCoo;//坐标系原点
    
//TODO init 初始化:release:
    //准备屏幕尺寸
    mWinSize = new Point();
    mCoo = new Point(500, 500);
    Utils.loadWinSize(getContext(), mWinSize);
    mGridPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    
//TODO drawGrid 绘制网格:release:
    HelpDraw.drawGrid(canvas, mWinSize, mGridPaint);
//TODO drawCoo 绘制坐标系:release:
    HelpDraw.drawCoo(canvas, mCoo, mWinSize, mGridPaint);
2).网格--路径辅助:com.toly1994.c.view.analyze.HelpPath#gridPath
代码语言:javascript
复制
/**
 * 绘制网格:注意只有用path才能绘制虚线
 *
 * @param step 小正方形边长
 * @param winSize 屏幕尺寸
 */
public static Path gridPath(int step, Point winSize) {
    Path path = new Path();
    for (int i = 0; i < winSize.y / step + 1; i++) {
        path.moveTo(0, step * i);
        path.lineTo(winSize.x, step * i);
    }
    for (int i = 0; i < winSize.x / step + 1; i++) {
        path.moveTo(step * i, 0);
        path.lineTo(step * i, winSize.y);
    }
    return path;
}
2).网格--绘制:com.toly1994.c.view.analyze.HelpDraw#drawGrid
代码语言:javascript
复制
/**
 * 绘制网格
 * @param canvas 画布
 * @param winSize 屏幕尺寸
 * @param paint 画笔
 */
public static void drawGrid(Canvas canvas, Point winSize, Paint paint) {
    //初始化网格画笔
    paint.setStrokeWidth(2);
    paint.setColor(Color.GRAY);
    paint.setStyle(Paint.Style.STROKE);
    //设置虚线效果new float[]{可见长度, 不可见长度},偏移值
    paint.setPathEffect(new DashPathEffect(new float[]{10, 5}, 0));
    canvas.drawPath(HelpPath.gridPath(50, winSize), paint);
}
3).辅助--获取屏幕尺寸:com.toly1994.c.view.analyze.Utils#loadWinSize
代码语言:javascript
复制
/**
 * 获得屏幕高度
 *
 * @param ctx 上下文
 * @param winSize 屏幕尺寸
 */
public static void loadWinSize(Context ctx, Point winSize) {
    WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics outMetrics = new DisplayMetrics();
    if (wm != null) {
        wm.getDefaultDisplay().getMetrics(outMetrics);
    }
    winSize.x = outMetrics.widthPixels;
    winSize.y = outMetrics.heightPixels;
}
4).坐标系--路径:com.toly1994.c.view.analyze.HelpPath#cooPath
代码语言:javascript
复制
/**
 * 坐标系路径
 *
 * @param coo     坐标点
 * @param winSize 屏幕尺寸
 * @return 坐标系路径
 */
public static Path cooPath(Point coo, Point winSize) {
    Path path = new Path();
    //x正半轴线
    path.moveTo(coo.x, coo.y);
    path.lineTo(winSize.x, coo.y);
    //x负半轴线
    path.moveTo(coo.x, coo.y);
    path.lineTo(coo.x - winSize.x, coo.y);
    //y负半轴线
    path.moveTo(coo.x, coo.y);
    path.lineTo(coo.x, coo.y - winSize.y);
    //y负半轴线
    path.moveTo(coo.x, coo.y);
    path.lineTo(coo.x, winSize.y);
    return path;
}
5).坐标系--绘制:com.toly1994.c.view.analyze.HelpDraw#drawCoo
代码语言:javascript
复制
/**
 * 绘制坐标系
 * @param canvas  画布
 * @param coo     坐标系原点
 * @param winSize 屏幕尺寸
 * @param paint   画笔
 */
public static void drawCoo(Canvas canvas, Point coo, Point winSize, Paint paint) {
    //初始化网格画笔
    paint.setStrokeWidth(4);
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    //设置虚线效果new float[]{可见长度, 不可见长度},偏移值
    paint.setPathEffect(null);
    //绘制直线
    canvas.drawPath(HelpPath.cooPath(coo, winSize), paint);
    //左箭头
    canvas.drawLine(winSize.x, coo.y, winSize.x - 40, coo.y - 20, paint);
    canvas.drawLine(winSize.x, coo.y, winSize.x - 40, coo.y + 20, paint);
    //下箭头
    canvas.drawLine(coo.x, winSize.y, coo.x - 20, winSize.y - 40, paint);
    canvas.drawLine(coo.x, winSize.y, coo.x + 20, winSize.y - 40, paint);
    //为坐标系绘制文字
    drawText4Coo(canvas, coo, winSize, paint);
}
/**
 * 为坐标系绘制文字
 *
 * @param canvas  画布
 * @param coo     坐标系原点
 * @param winSize 屏幕尺寸
 * @param paint   画笔
 */
private static void drawText4Coo(Canvas canvas, Point coo, Point winSize, Paint paint) {
    //绘制文字
    paint.setTextSize(50);
    canvas.drawText("x", winSize.x - 60, coo.y - 40, paint);
    canvas.drawText("y", coo.x - 40, winSize.y - 60, paint);
    paint.setTextSize(25);
    //X正轴文字
    for (int i = 1; i < (winSize.x - coo.x) / 50; i++) {
        paint.setStrokeWidth(2);
        canvas.drawText(100 * i + "", coo.x - 20 + 100 * i, coo.y + 40, paint);
        paint.setStrokeWidth(5);
        canvas.drawLine(coo.x + 100 * i, coo.y, coo.x + 100 * i, coo.y - 10, paint);
    }
    //X负轴文字
    for (int i = 1; i < coo.x / 50; i++) {
        paint.setStrokeWidth(2);
        canvas.drawText(-100 * i + "", coo.x - 20 - 100 * i, coo.y + 40, paint);
        paint.setStrokeWidth(5);
        canvas.drawLine(coo.x - 100 * i, coo.y, coo.x - 100 * i, coo.y - 10, paint);
    }
    //y正轴文字
    for (int i = 1; i < (winSize.y - coo.y) / 50; i++) {
        paint.setStrokeWidth(2);
        canvas.drawText(100 * i + "", coo.x + 20, coo.y + 10 + 100 * i, paint);
        paint.setStrokeWidth(5);
        canvas.drawLine(coo.x, coo.y + 100 * i, coo.x + 10, coo.y + 100 * i, paint);
    }
    //y负轴文字
    for (int i = 1; i < coo.y / 50; i++) {
        paint.setStrokeWidth(2);
        canvas.drawText(-100 * i + "", coo.x + 20, coo.y + 10 - 100 * i, paint);
        paint.setStrokeWidth(5);
        canvas.drawLine(coo.x, coo.y - 100 * i, coo.x + 10, coo.y - 100 * i, paint);
    }
}

二、Canvas绘制基础图形(如果觉得简单可跳过)

以前看到一个类有很多方法都有些不耐烦,这么多,怎么记得住。 现在看到一个类有很多方法,--哇,太好了,哈哈,竟然连这方法都有,作者真给力省的我实现了。 Canvas图形绘制的API,所有的我分了一下类:如下(颜色、点、线、矩形、类圆、文字、图片、其他) 下面一一介绍:

Canvas绘制API


1.绘制颜色

绘制颜色

代码语言:javascript
复制
    /**
     * 绘制颜色(注意在画坐标系前绘制,否则后者覆盖)
     * @param canvas
     */
    private void drawColor(Canvas canvas) {
//        canvas.drawColor(Color.parseColor("#E0F7F5"));
//        canvas.drawARGB(255, 224, 247, 245);
//        三者等价
        canvas.drawRGB(224, 247, 245);
    }

绘制颜色.png


2.绘制点

绘制点.png

代码语言:javascript
复制
    /**
     * 绘制点
     * @param canvas
     */
    private void drawPoint(Canvas canvas) {
        //绘制点
        canvas.drawPoint(100, 100, mRedPaint);
        ////绘制一组点,坐标位置由float数组指定(必须是2的倍数个)
        canvas.drawPoints(new float[]{
                400, 400, 500, 500,
                600, 400, 700, 350,
                800, 300, 900, 300
        }, mRedPaint);
    }

绘制点.png


3.绘制直线

绘制线

代码语言:javascript
复制
/**
 * 绘制线
 * @param canvas
 */
private void drawLine(Canvas canvas) {
    canvas.drawLine(500, 200, 900, 400, mRedPaint);
    //绘制一组点,坐标位置由float数组指定(必须是4的倍数个)
    canvas.drawLines(new float[]{
            200, 200, 400, 200,
            400, 200, 200, 400,
            200, 400, 400, 400
    }, mRedPaint);
}

绘制线.png


4.绘制矩形

绘制矩形.png

代码语言:javascript
复制
    /**
     * 绘制矩形
     *
     * @param canvas
     */
    private void drawRect(Canvas canvas) {
        canvas.drawRect(100, 100, 500, 300, mRedPaint);
        //等价上行
//        Rect rect = new Rect(100, 100, 500, 300);
//        canvas.drawRect(rect,mRedPaint);
        //(左上右下X圆角,Y圆角)
        canvas.drawRoundRect(100 + 500, 100, 500 + 500, 300, 50, 50, mRedPaint);
    }

绘制矩形.png


5.绘制类圆

绘制类圆.png

代码语言:javascript
复制
    /**
     * 绘制类圆
     *
     * @param canvas
     */
    private void drawLikeCircle(Canvas canvas) {
        //绘制圆(矩形边界,画笔)
        canvas.drawCircle(650, 200, 100, mRedPaint);
//        canvas.drawOval(100, 100, 500, 300, mRedPaint);
        //等价上行
        //绘制椭圆(矩形边界,画笔)
        RectF rect = new RectF(100, 100, 500, 300);
        canvas.drawOval(rect, mRedPaint);

        RectF rectArc = new RectF(100 + 500, 100, 500 + 500, 300);
        //绘制圆弧(矩形边界,开始角度,扫过角度,使用中心?边缘两点与中心连线区域:边缘两点连线区域)
        canvas.drawArc(rectArc, 0, 90, true, mRedPaint);

        RectF rectArc2 = new RectF(100 + 500 + 300, 100, 500 + 500 + 300, 300);
        //绘制圆弧(矩形边界,开始角度,扫过角度,使用中心?边缘两点与中心连线区域:边缘两点连线区域)
        canvas.drawArc(rectArc2, 0, 90, false, mRedPaint);
    }

绘制类圆.png


6.绘制图片

绘制图片.png

代码语言:javascript
复制
    /**
     * 绘制图片
     * @param canvas
     */
    private void drawBitmap(Canvas canvas) {
        //1.定点绘制图片
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
        canvas.drawBitmap(bitmap, 100, 100, mRedPaint);
        //2.适用变换矩阵绘制图片
        Matrix matrix = new Matrix();
        //设置变换矩阵:缩小3倍,斜切0.5,右移150,下移100
        matrix.setValues(new float[]{
                1, 0.5f, 1500 * 3,
                0, 1, 100 * 3,
                0, 0, 3
        });
        canvas.drawBitmap(bitmap, matrix, mRedPaint);

        //3.图片适用矩形区域不剪裁
        RectF rectf1 = new RectF(100 + 900, 100, 600 + 900, 400);
        canvas.drawBitmap(bitmap, null, rectf1, mRedPaint);

        //4.图片裁剪出的矩形区域
        Rect rect = new Rect(300, 300, 400, 400);
        //图片适用矩形区域
        RectF rectf2 = new RectF(100 + 900, 100 + 400, 600 + 900, 400 + 400);
        canvas.drawBitmap(bitmap, rect, rectf2, mRedPaint);
    }

绘制图片.png


7.绘制Picture

1).一开始挺纳闷Picture不就是图片吗?然后翻了一下API:

代码语言:javascript
复制
/**
 * A Picture records drawing calls (via the canvas returned by beginRecording)
 * and can then play them back into Canvas (via {@link Picture#draw(Canvas)} or
 * {@link Canvas#drawPicture(Picture)}).For most content (e.g. text, lines, rectangles),
 * drawing a sequence from a picture can be faster than the equivalent API
 * calls, since the picture performs its playback without incurring any
 * method-call overhead.
 *
 * <p class="note"><strong>Note:</strong> Prior to API level 23 a picture cannot
 * be replayed on a hardware accelerated canvas.</p>
 
 一个Picture类记录绘制(通过beginRecording方法返回的Canvas),可以展示这个Canvas
 到其他Canvas上(通过Picture#draw(Canvas)或者Canvas#drawPicture(Picture)),
 对于大多数的内容,从picture绘制都要比相应的API要快速,因为picture的展现不会招致方法调用开销
 在API级别23之前,无法在硬件加速画布上展示Picture(自译,仅供参考)

2).通过一段代码你就能很清楚它是干嘛用的

如果绘制一个品字,需要这样:

testPicture.png

代码语言:javascript
复制
  private void drawPicture(Canvas canvas) {
        canvas.drawRect(100, 0, 200, 100, mRedPaint);
        canvas.drawRect(0, 100, 100, 200, mRedPaint);
        canvas.drawRect(200, 100, 300, 200, mRedPaint);
    }

如果想要复用这个品字形,大多数人知道,平移画布,复制粘贴, 对于少量的代码,这还可以接收,如果是非常复杂的图形,每次绘制重复的内容,会浪费性能

代码语言:javascript
复制
 private void drawPicture(Canvas canvas) {
     //创建Picture对象
     Picture picture = new Picture();
     //确定picture产生的Canvas元件的大小,并生成Canvas元件
     Canvas recodingCanvas = picture.beginRecording(canvas.getWidth(), canvas.getHeight());
     //Canvas元件的操作
     recodingCanvas.drawRect(100, 0, 200, 100, mRedPaint);
     recodingCanvas.drawRect(0, 100, 100, 200, mRedPaint);
     recodingCanvas.drawRect(200, 100, 300, 200, mRedPaint);
     //Canvas元件绘制结束
     picture.endRecording();
     
     canvas.save();
     canvas.drawPicture(picture);//使用picture的Canvas元件
     canvas.translate(0, 300);
     picture.draw(canvas);//同上:使用picture的Canvas元件
     canvas.drawPicture(picture);
     canvas.translate(350, 0);
     canvas.drawPicture(picture);
     canvas.restore();

testPicture2.png

Picture相当于先拍一张照片,并且是在别的Canvas上,在别的Canvas上,在别的Canvas上! 重要的话说三遍:当需要的时候在贴在当前的canvas上,picture绘制的优势就是节能减排 当有大量复杂内容需要复用,Picture这个的canvas元件是不二的选择:


8.绘制文字(文字的效果有Paint决定,细节将在Paint篇介绍)

绘制文字

代码语言:javascript
复制
    /**
     * 绘制文字
     *
     * @param canvas
     */
    private void drawText(Canvas canvas) {
        mRedPaint.setTextSize(100);
        canvas.drawText("张风捷特烈--Toly", 200, 300, mRedPaint);
    }

绘制文字.png

无聊的代码终于敲完了,进入正题。


三、Canvas的画布变换

以前对Canvas的变换很厌倦,现在看了键值是神技 作为一代PS大神的我,理解Canvas状态保存与恢复本应易如反掌,为何最近才豁然开朗

1.先看下面的图形:将坐标系原点设为(500,500)
代码语言:javascript
复制
    private void stateTest(Canvas canvas) {
        canvas.drawLine(mCoo.x + 500, mCoo.y + 200, mCoo.x + 900, mCoo.y + 400, mRedPaint);
//        canvas.rotate(45);
        canvas.drawRect(mCoo.x + 100, mCoo.x + 100, mCoo.y + 300, mCoo.y + 200, mRedPaint);
    }

状态测试1.png

问题来了,想画一个斜45度的矩形怎么办? 貌似没有斜矩形的API,一个一个点找,貌似太麻烦了,我把纸转一下不就行了吗! 纸就是Canvas,看一下API,果然有rotate()方法,怀着忐忑的心情:

代码语言:javascript
复制
    private void stateTest(Canvas canvas) {
        canvas.drawLine(mCoo.x + 500, mCoo.y + 200, mCoo.x + 900, mCoo.y + 400, mRedPaint);
        canvas.rotate(45);
        canvas.drawRect(mCoo.x + 100, mCoo.x + 100, mCoo.y + 300, mCoo.y + 200, mRedPaint);
    }

果然转得天翻地覆

状态测试旋转.png


2.图层的概念

PS中的图层可谓PS的精华,它保证了在一个图层中绘制而不会影响到其他的图层 在Canvas中每次的save()都存将先前的状态保存下来,产生一个新的绘图层, 我们可以随心所欲地地画而不会影响其他已画好的图,最后用restore()将这个图层合并到原图层 这像是栈的概念,每次save(),新图层入栈(注意可以save多次),只有栈顶的层可以进行操作,restore()弹栈

图层.png


3.旋转画布:rotate()
代码语言:javascript
复制
    private void stateTest(Canvas canvas) {
        canvas.drawLine(mCoo.x + 500, mCoo.y + 200, mCoo.x + 900, mCoo.y + 400, mRedPaint);
        canvas.drawRect(mCoo.x + 100, mCoo.x + 100, mCoo.y + 300, mCoo.y + 200, mRedPaint);
        canvas.save();//保存canvas状态
        //(角度,中心点x,中心点y)
        canvas.rotate(45, mCoo.x + 100, mCoo.y + 100);
        mRedPaint.setColor(Color.parseColor("#880FB5FD"));
        canvas.drawRect(mCoo.x + 100, mCoo.x + 100, mCoo.y + 300, mCoo.y + 200, mRedPaint);
        canvas.restore();//图层向下合并
    }

定点旋转.png

4.平移画布:translate():写一堆mCoo,也就是让画布移动一下而已

效果必变,是不是清爽许多

代码语言:javascript
复制
    private void stateTest(Canvas canvas) {
        canvas.save();
        canvas.translate(mCoo.x, mCoo.y);//将原点平移到坐标系原点
        canvas.drawLine(500, 200, 900, 400, mRedPaint);
        canvas.drawRect(100, 100, 300, 200, mRedPaint);
        canvas.save();//保存canvas状态
        //(角度,中心点x,中心点y)
        canvas.rotate(45, 100, 100);
        mRedPaint.setColor(Color.parseColor("#880FB5FD"));
        canvas.drawRect(100, 100, 300, 200, mRedPaint);
        canvas.restore();//图层向下合并
        canvas.restore();
    }

平移.png

5.缩放画布:scale()
代码语言:javascript
复制
    private void stateTest(Canvas canvas) {
        canvas.save();
        canvas.translate(mCoo.x, mCoo.y);//将原点平移到坐标系原点
        canvas.drawLine(500, 200, 900, 400, mRedPaint);
        canvas.drawRect(100, 100, 300, 200, mRedPaint);
        canvas.save();//保存canvas状态
        //(角度,中心点x,中心点y)
        canvas.scale(2, 2, 100, 100);
        mRedPaint.setColor(Color.parseColor("#880FB5FD"));
        canvas.drawRect(100, 100, 300, 200, mRedPaint);
        canvas.restore();//图层向下合并
        canvas.restore();
    }

定点缩放.png

6.斜切画布:scale()
代码语言:javascript
复制
    private void stateTest(Canvas canvas) {

        canvas.save();
        canvas.translate(mCoo.x, mCoo.y);//将原点平移到坐标系原点
        canvas.drawLine(500, 200, 900, 400, mRedPaint);
        canvas.drawRect(100, 100, 300, 200, mRedPaint);
        canvas.save();//保存canvas状态
        canvas.skew(1f,0f);
        mRedPaint.setColor(Color.parseColor("#880FB5FD"));
        canvas.drawRect(100, 100, 300, 200, mRedPaint);
        canvas.restore();//图层向下合并
        canvas.restore();
    }

斜切.png

7.画布选择保存状态:

canvas保存状态.png

代码语言:javascript
复制
public int save (int saveFlags)
默认:MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG

ALL_SAVE_FLAG               保存全部状态
CLIP_SAVE_FLAG              过期---仅保存剪辑区(不作为图层)
CLIP_TO_LAYER_SAVE_FLAG     过期---仅剪裁区作为图层保存
FULL_COLOR_LAYER_SAVE_FLAG  过期---仅保存图层的全部色彩通道
HAS_ALPHA_LAYER_SAVE_FLAG   过期---仅保存图层的alpha(不透明度)通道
MATRIX_SAVE_FLAG            过期---仅保存Matrix信息( translate, rotate, scale, skew)
代码语言:javascript
复制
    int count = canvas.getSaveCount();//获取图层的个数3
    canvas.restoreToCount(1);//直接恢复到第几个图层
四、Canvas的裁剪
1.可见主要就两种类型,内裁剪和外裁剪,Op的操作被废弃了

canvas剪裁.png

2.内剪裁:(区域内的之后绘制的内容保存)
代码语言:javascript
复制
    private void clip(Canvas canvas) {
        //剪裁区域
        Rect rect = new Rect(20, 100, 250, 300);
        canvas.clipRect(rect);
        canvas.drawRect(0, 0, 200, 300, mRedPaint);
    }

内剪裁.png

3.外剪裁:(区域外的之后绘制的内容保存)--注意API26及以上可用
代码语言:javascript
复制
    private void clip(Canvas canvas) {
        //剪裁区域
        Rect rect = new Rect(20, 100, 250, 300);
        canvas.clipOutRect(rect);
        canvas.drawRect(0, 0, 200, 300, mRedPaint);
    }

外剪裁.png

Canvas的相关内容就到这里(注:路径的绘制会在Path篇精讲),下一节将带来画笔Paint的知识


后记:捷文规范
1.本文成长记录及勘误表

项目源码

日期

备注

V0.1--无

2018-11-5

Android关于Canvas你所知道的和不知道的一切

V0.2--无

2018-11-6

增加绘制Picture的内容

2.更多关于我

笔名

QQ

微信

爱好

张风捷特烈

1981462002

zdl1994328

语言

我的github

我的简书

我的CSDN

个人网站

3.声明

1----本文由张风捷特烈原创,转载请注明 2----欢迎广大编程爱好者共同交流 3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 4----看到这里,我在此感谢你的喜欢与支持

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.11.05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如果将View、Canvas、Paint、Coder(编写代码的人)做个类比:
  • 一、前期准备:
    • 1.自定义View中的canvas:
      • 2.准备网格与坐标系
        • 1).使用方式:
        • 2).网格--路径辅助:com.toly1994.c.view.analyze.HelpPath#gridPath
        • 2).网格--绘制:com.toly1994.c.view.analyze.HelpDraw#drawGrid
        • 3).辅助--获取屏幕尺寸:com.toly1994.c.view.analyze.Utils#loadWinSize
        • 4).坐标系--路径:com.toly1994.c.view.analyze.HelpPath#cooPath
        • 5).坐标系--绘制:com.toly1994.c.view.analyze.HelpDraw#drawCoo
      • 二、Canvas绘制基础图形(如果觉得简单可跳过)
        • 1.绘制颜色
        • 2.绘制点
        • 3.绘制直线
        • 4.绘制矩形
        • 5.绘制类圆
        • 6.绘制图片
        • 7.绘制Picture
        • 8.绘制文字(文字的效果有Paint决定,细节将在Paint篇介绍)
        • 三、Canvas的画布变换
        • 1.先看下面的图形:将坐标系原点设为(500,500)
        • 2.图层的概念
        • 3.旋转画布:rotate()
        • 4.平移画布:translate():写一堆mCoo,也就是让画布移动一下而已
        • 5.缩放画布:scale()
        • 6.斜切画布:scale()
        • 四、Canvas的裁剪
        • 1.可见主要就两种类型,内裁剪和外裁剪,Op的操作被废弃了
        • 2.内剪裁:(区域内的之后绘制的内容保存)
        • 3.外剪裁:(区域外的之后绘制的内容保存)--注意API26及以上可用
      • 后记:捷文规范
        • 1.本文成长记录及勘误表
        • 2.更多关于我
        • 3.声明
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档