android高级开发自定义View-canvas的save和restore方法的使用-大厂高频面试题

背景:

hi,粉丝朋友们:
大家好!上星期举办的framework模拟面试活动,许多粉丝也在积极探讨面试过程中的一些问题。比如今天要讲解的问题:
一般很多做应用同学简历都会写一个"熟练自定义view",这个技能基本上android高级应用开发都很多同学会写。面试官针对这个技能的面试比较容易考察的问题就是:
你是否知道canvas里面有一个save和restore方法,针对这个canvas的save和restore方法你可以说说对他的理解吗?

哈哈哈有没有很熟悉这个面试问题,先说一下为啥要考查这个问题呢?
其实很多高级ui,其实大部分时候都需要比较复杂的绘制,大部分时候都需要灵活掌握绘制相关方法,canvas属于最为频繁的一种,而且复杂ui经常需要涉及到旋转,平移,等操作,这时候就需要save和restore的出场。

Canvas的save和restore介绍

/**
 * Saves the current matrix and clip onto a private stack.
 * <p>
 * Subsequent calls to translate,scale,rotate,skew,concat or clipRect,
 * clipPath will all operate as usual, but when the balancing call to
 * restore() is made, those calls will be forgotten, and the settings that
 * existed before the save() will be reinstated.
 *
 * @return The value to pass to restoreToCount() to balance this save()
 */
public int save() {
    return nSave(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
}

可以看到这里注释已经比较清楚,保存当前canvas的矩阵matrix和裁剪clip数据到一个stack中

再来看看restore方法:

/**
     * This call balances a previous call to save(), and is used to remove all
     * modifications to the matrix/clip state since the last save call. It is
     * an error to call restore() more times than save() was called.
     */
    public void restore() {
        if (!nRestore(mNativeCanvasWrapper)
                && (!sCompatibilityRestore || !isHardwareAccelerated())) {
            throw new IllegalStateException("Underflow in restore - more restores than saves");
        }
    }

这里的restore和save一般是对应的,前面save是保存canvas的matrix,clip到stack,这里restore就是从stack把顶部的matrix和clip取出应用。
如下图所示:
在这里插入图片描述
这里的save1,save2,save3其实本质可以认为是某一个时刻的matrix和clip的数据。restore时候就是获取这个save数据,然后应用到canvas上,当然肯定应用前canvas会被reset。

总结大白话理解:
canvas经常可能因为绘制需求,需要对canvas进行旋转平移等绘制,但是旋转平移后整个坐标系就变化了,下一部分还要绘制时候,可能想基于原始坐标来,但是已经被平移了旋转了,怎么回到原来呢?
难道还要挨个旋转回去和平移回去么?当然不是哈,这样做的话大家都感觉太傻了,所以就有了今天讲解的save和restore出现。在canvas平移旋转前save,然后想回到原来既可以调restore

代码具体应用理解:

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        //第一个基于原点坐标绘制的离左边距离10
        paint.setColor(Color.RED);
        canvas.drawRect(10,10,70,30,paint);
        
        //canvas已经平移了100
        canvas.translate(100,100);
        paint.setColor(Color.YELLOW);
        
        //这时候绘制的坐标是0,但是因为平移了,所以间隔原点其实是100
        canvas.drawRect(0,10,60,30,paint);

        paint.setColor(Color.BLACK);
        
        //这时候绘制的坐标是200,但是因为平移了,所以间隔原点其实是200+100
        canvas.drawRect(200,10,320,30,paint);


    }

在这里插入图片描述

但是第三个黑块如果不想跟随第二个黄绘制时候的平移影响怎么办??代码如下:

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        //第一个基于原点坐标绘制的离左边距离10
        paint.setColor(Color.RED);
        canvas.drawRect(10,10,70,30,paint);
        //平移前对canvas进行save
        canvas.save();
        
        //canvas已经平移了100
        canvas.translate(100,100);
        paint.setColor(Color.YELLOW);
        
        //这时候绘制的坐标是0,但是因为平移了,所以间隔原点其实是100
        canvas.drawRect(0,10,60,30,paint);
 				//第二个绘制完成后进行restore
        canvas.restore();
       
        paint.setColor(Color.BLACK);
        
        //这时候绘制的坐标是200,那么就是200
        canvas.drawRect(200,10,320,30,paint);


    }

执行结果如下:
在这里插入图片描述

黑色重新回到原始坐标系,没有受到第二个平移的影响。

更多精彩内容手把手视频或关注下面公众号“千里马学框架”:
https://www.bilibili.com/video/BV1TK4y1c7Ku/

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

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

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

打赏作者

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

抵扣说明:

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

余额充值