图层(Layer):
  • 每次调用canvas.drawXXX系列函数,都会生成一个透明图层来绘制这个图形
画布(Bitmap):
  • 每块画布都是一个Bitmap,所有的图像都是画在这个Bitmap上的,画布有两种:
    * 一种是View的原始画布,通过onDraw(Canvas canvas)的方法传入的,canvas对应的就是原始的画布,控件的背景就是华仔这块 画布上的
    * 另一种是人造画布,通过saveLayer()、new Canvas(bitmap)等函数来人为的创建一块新的画布,调用saveLayer()函数以后所有的绘图都是在新创建出来的画布上进行的,只有在调用restore()、restoreToCount()之后才会返回原始的界面
Canvas:
  • Canvas是画布的表现形式,所绘制的所有东西都是通过Canvas实现的,可以将Canvas理解成绘图的工具,生成Canvas的方式只有一种new Canvas(Bitmap),即只能通过Bitmap生成,无论是原始画布还是人造画布,所有的画布最后都是通过Canvas画到画布上的。Canvas这个工具利用他封装的函数进行绘图操作,其实就是在对应的Bitmap上进行绘图操作,如果利用Canvas.clipXXX函数进行剪裁,就是剪裁对应的Bitmap,之后再利用Canvas的绘图区域就会变小。
总结:

Bitmap是画布 -->Canvas在Bitmap上绘图
Bitmap画布–>Layer产生图层–>Canvas绘图–>覆盖在画布上显示

saveLayer()和saveLayerAlpha()函数:

saveLayer()
//bounds:新建画布的尺寸
//paint:画笔实例
//saveFlags:新建画布的标识
public int saveLayer(RectF bounds, Paint paint, int saveFlags)
  • saveLayer()会新建一个新的画布,之后所有的绘图动作都会在新的画布上进行
注意:

(1) saveLayer()函数后的所有动作都只对新建画布有效

public class SaveLayerUseExample extends View {private Paint paint;private Bitmap bitmap;public SaveLayerUseExample(Context context, AttributeSet attrs) {super(context, attrs);paint = new Paint();paint.setColor(Color.RED);bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dog);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawBitmap(bitmap, 0, 0, paint);int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), paint, Canvas.ALL_SAVE_FLAG);//将新建的图层水平斜切45度,在进行绘画一个矩形,但是只是对新建的画布产生影响,并不会对原有的画布有影响canvas.skew(1.732f, 0);canvas.drawRect(0, 0, 150, 160, paint);canvas.restoreToCount(layerId);}
}

(2)通过Rect指定矩形大小就是新建的画布大小:

在saveLayer()函数的参数中,可以通过指定Rect对象或者指定4个点来指定一个矩形,这个矩形的大小就是新建的画布大小,而且在创建画布的时候一定要选择适当的大小,否则APP会发生OOM
setLayerAlpha()函数的使用:
//相比于saveLayer()函数,多了一个alpha的参数,用于指定新建画布的透明度,取值范围0~255,可以使用16进制的oxAA表示,取0时表示全透明
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags)public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags)
  • saveLayerAlpha()会创建一个新的画布,以后的绘图就在这个新建的画布上完成,但是这块画布是有透明度的,通过alpha参数进行指定

eg:

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawBitmap(bitmap, 0, 0, paint);int layerId = canvas.saveLayerAlpha(0, 0, 200, 200, 100, Canvas.ALL_SAVE_FLAG);canvas.drawColor(Color.GRAY);canvas.restoreToCount(layerId);}
}
Flag的具体含义:
  • Canvas中有以下几个save系列函数:
public int save();
public int save(int saveFlags)
public int saveLayer(RectF bounds, Paint paint, int saveFlags)
public int saveLayer(float left, float top, float right , float bottom, Paint paint, int saveFlags)
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags)
public int saveLayerAlpha(float left, float top. float right, float bottom, int alpha, int saveFalgs)
  • save()和saveLayer()区别:
save不会创建一个画布,saveLayer创建一个新的画布
  • save()和saveLayer()的flag的区别:
Flag 含义 适用范围
ALL_SAVE_FLAG 保存所有的标识 save()、saveLayer()
MATRIX_SAVE_FLAG 仅保存Canvas的matrix数组大小 save()、saveLayer()
CLIP_SAVE_FLAG 仅保存Canvas的当前大小 save(), saveLayer()
HAS_ALPHA_LAYER_SAVE_FLAG 标识新建的bmp具有透明度,在与上层画布结合的时候,透明位置显示上层图像,与FULL_COLOR_LAYER_SAVE_FLAG冲突,若同时指定,则以HAS_ALPHA_LAYER_SAVE_FLAG为主 saveLayer()
FULL_COLOR_LAYER_SAVE_FLAG 标识新建的bmp颜色完全独立,在与上层的画布结合的时候,先清空上层画布再覆盖上去 saveLayer()
CLIP_TO_LAYER_SAVE_FLAG 在保存图层前先把当前画布根据bounds剪裁,与CLIP_SAVE_FLAG冲突,若同时指定,则以CLIP_SAVE_FLAG为主 saveLayer()
注意:在保存一块画布的状态的时候,需要保存哪些内容
  • 位置信息:MATRIX_SAVE_FLAG
  • 大小信息:CLIP_SAVE_FLAG
Flag之MATRIX_SAVE_FLAG
  • 平移,旋转,缩放,扭曲都是利用位置矩阵Matrix实现的,而MATRIX_SAVE_FLAG标识仅保存这个位置矩阵,除此之外的任何内容都不会进行保存
public class MATRIX_SAVE_FLAG_View extends View {private Paint paint;public MATRIX_SAVE_FLAG_View(Context context, AttributeSet attrs) {super(context, attrs);setLayerType(LAYER_TYPE_SOFTWARE, null);paint = new Paint();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//bao保存画布的位置信息canvas.save();//将画布旋转40度canvas.rotate(40);//画一个矩形canvas.drawRect(100, 0, 200, 100, paint);//恢复画布canvas.restore();paint.setColor(Color.BLACK);canvas.drawRect(100, 0, 200, 100, paint);}
}
  • 首先将画布的位置信息保存,然后绘制一个矩形,之后将画布恢复,在最后一个位置绘制 一个矩形,分析结果可以得知之前的保存操作是将画布的位置信息保存,但是如果使用MATRIX_SAVE_FLAG的flag进行保存,则不会保存画布的大小信息,也就是说裁剪之后的画布是不会被复原的
结论:
  • MATRIX_SAVE_FLAG标识只会保存位置矩阵,在恢复时也只会恢复画布的位置信息,除此之外的任何信息(比如画布的大小信息是不会被恢复的,save()和saveLayer()相同

  • saveLayer()函数在使用Canvas.MATRIX_SAVE_FLAG标识时,需要与Canvas.HAS_ALPHA_LAYER_SAVE_FLAG一起使用,否则新建画布所在区域原来的图像将被清空

Flag之CLIP_SAVE_FLAG
  • 这个标识是仅保存Canvas的裁剪信息,并不保存位置信息,只会恢复大小,并不会恢复旋转,位置信息
canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.drawColor(Color.BLUE);
canvas.clipRect(100, 0, 200, 100);
canvas.restore();
canvas.drawColor(Color.GRAY);
  • 首先将画布绘制蓝色并保存,再进行裁剪,裁剪后恢复,并画布绘制成灰色,最后发现全屏为灰色,则证明裁剪的画布被恢复。但是当你先绘制一个矩形,之后按照此flag保存画布,旋转40度后再恢复,再绘制一个矩形,会发现绘制的矩形旋转40度,所以证明这个flag只会对裁剪进行恢复,并不会对位置的信息进行恢复
结论:
  • CLIP_SAVE_FLAG:只会保存剪裁的信息,再恢复时也只会恢复画布的裁剪信息,除此之外的任何信息是不会被恢复的,save()和saveLayer()相同
  • saveLayer()函数在使用Canvas.CLIP_SAVE_FLAG标识时,需要与Canvas.HAS_ALPHA_LAYER_SAVE_FLAG标识一起使用,否则新建 画布所在区域的原来的图像将被清空
flag之FULL_COLOR_LAYER_FLAG和HAS_ALPHA_LAYER_SAVE_FLAG
  • HAS_ALPHA_LAYER_SAVE_FLAG:表示新建的画布在与上一层画布合成时,不会将上一层画布的内容清空,而是直接覆盖在上一层画布上的
  • FULL_COLOR_LAYER_FLAG:表示新建的画布在与上一层画布合成时,先将上一层画布的对应区域清空,再覆盖在上面
  1. 这两个标签都是saveLayer()专用,使用时要禁用硬件加速,在API26以及以后的版本中,该falg已经失效
  2. 两者是冲突的,使用时以HAS_ALPHA_LAYER_SAVE_FLAG为主
  3. 当既没有指定使用的是两者中的哪一个时,默认以FULL_COLOR_LAYER_SAVE_FLAG标识
flag之CLIP_TO_LAYER_SAVE_FLAG:
  • 在新建bitmap之前,先对Canvas进行剪裁,在Canvas内部的画布被剪裁后,利用saveLayer()函数生成的画布大小与剪裁后的画布大小相同;而且再利canvas.restore()函数进行恢复时,只会把saveLayer()函数新建画布的内容叠加,而不会将剪裁的Canvas恢复(API23失效)
  • 在与CLIP_SAVE_FLAG标识共用时,以CLIP_SAVE_FLAG为主
flag之ALL_SAVE_FLAG:
  • 它是所有标识的公共集合
  • 对于save()来说,ALL_SAVE_FLAG = MATRIX_SAVE_FLAG|CLIP_SAVE_FLAG,即保存位置信息和裁剪信息,因为save(int flag)函数只能使用MATRIX_SAVE_FLAG和CLIP_SAVE_FLAG
  • 对于saveLayer()来说, ALL_SAVE_FLAG = MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG | HAS_ALPHA_LAYER_SAVE_FLAG,即保存的位置信息和裁剪信息,新建画布在与上一层画布合成时, 不清空原画布的内容

注意:上述的Flag除了ALL_SAVE_FLAG以外的所有标识在API26以后已经废弃,在低版本中仍然可以使用

Canvas与图层(二)画布与图层相关推荐

  1. Android 高级UI解密 (三) :Canvas裁剪 与 二维、三维Camera几何变换(图层Layer原理)

    Android的绘图机制是核心内容之一,无论是什么样的功能最终都是以图像的形式呈现给用户.因此掌握Android的绘图技巧,有助于Android理解层次的提高,在面对产品经理提出的idea时也更有底气 ...

  2. CAD 二次开发 图层操作(1)创建图层

    CAD二次开发的资料比较少,除了李冠亿先生的<深居浅出AutoCAD二次开发>这本书之外,目前没有找到合适的参考资料.现将自己工作中用的的一些方法贴出来.方便各位网友快速入门. #regi ...

  3. c# cad 二次开发 类库 netload 图层操作、创建图层、删除图层、设置当前图层等

    c# cad 二次开发 类库 netload 图层操作.创建图层.删除图层.设置当前图层等 using Autodesk.AutoCAD.ApplicationServices; using Auto ...

  4. ps中如何让图层在画布内水平居中

    下图每个小logo图案距离它们的上参考线的距离均为10px,而我们如何让图层在画布内水平居中??? 如上图中三个图层的图案是用来给Html/Css中的background属性使用的,虽然可以通过鼠标拖 ...

  5. linux修改index属性,WPF 通过设置Canvas.ZIndex属性修改图像的图层

    WPF 通过设置Canvas.ZIndex属性修改图像的图层 WPF 通过设置Canvas.ZIndex属性修改图像的图层 对Canvas.ZIndex,MSDN的解释是:获取或设置 Canvas 中 ...

  6. 南方数码iData数据工厂二次开发图层选择

    南方数码的idata数据工厂目前有针对第三次全国土地调查的版本.下面我们来学习一下有关图层的一个小案例.这里案例是通过指定图层名称,然后选择图层.如果数据库中存在指定名称的图层,然后遍历图层的所有实体 ...

  7. 小猿圈web前端简述canvas如何实现二维码和图片合成

    你经常看到活动海报什么的,上都是有各种宣传文案以及二维码形成的,你知道怎么用canvas实现二维码和图片合成,下面小猿圈Linux讲师为你详细介绍一下canvas如何实现二维码和图片合成的. 使用ur ...

  8. 中望3D 2020 图层管理器(图层的设置+移动图层+复制图层)

    图层在二维CAD中的作用是对不同线型.线宽.标注.打印等进行整理归类,而在三维CAD中,只有小部分三维CAD软件是具有图层这个概念的,有助于设计师在模具等设计中对不同零件进行整理归类,使设计工作更快捷 ...

  9. ArcGIS Pro(ArcMap)中利用自带地理处理工具实现线图层批量裁剪面图层

    近日被同事提问ArcGIS中线图层如何裁剪面图层,以前也只知道ArcMap中高级编辑里的"分割面"可以实现,在操作步骤比较复杂,已经忘记了如何操作,而且ArcGIS Pro中貌似已 ...

最新文章

  1. java用户界面项目_结对项目(带图型用户界面)Java实现【柴政-陈起廷】
  2. The setting logImpl is not known
  3. PHP - declare tick
  4. 在JSP页面中获取系统当前日期时间
  5. 硬核黑科技、技术大咖、AI 音乐节……科大讯飞全球 1024 开发者节太燃了!
  6. 【李宏毅2020 ML/DL】P86-87 More about Domain Adaptation
  7. Deep Convolutional Network Cascade for Facial Point Detection论文算法解析
  8. 【收藏推荐】Markdown常用LaTeX数学符号公式
  9. SAP ABAP开发视频学习(视频教程)
  10. html模拟鼠标点击图标,易语言模拟鼠标点击实现方法
  11. 双系统安装deepin20_win10安装deepin双系统
  12. python获取json数据中某个字段_python获取json数据中某个字段
  13. 教你如何用CAD画向日葵
  14. 小程序怎么接入第三方客服工具?
  15. sqlserver Month()函数取日期不足两位的加 0(转载)
  16. 鸿蒙和小米哪个值得入手,鸿蒙系统能够吸引小米的优势是什么
  17. iOS AudioQueue实现音频的录制和播放(附Demo)
  18. 极米、当贝、坚果3000内的投影仪有什么推荐?
  19. 如何用matlab解异或方程,Matlab-6:解非线性方程组newton迭代法
  20. Buhtrap在最新监控活动中使用多个0 day漏洞

热门文章

  1. 锚点定位并距离顶部一定偏移
  2. 快手与央视达成合作:除夕晚8点,上快手看春晚
  3. Nginx配置详解笔记
  4. Federated Averaging算法
  5. 流媒体时代,如何看待音乐版权
  6. 使用Spring-Data-Redis存储对象(redisTemplate)
  7. Android7.0更换系统默认输入法
  8. 软件系统设计-10-防御式编程
  9. UE4昼夜交替的简单实现
  10. 年度榜单:2012年最流行的28款免费英文字体素材