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.
*
* 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/