探索flutter框架开发的app在移动应用市场的潜力与挑战
1016
2022-11-16
【Android UI】Canvas 画布 ③ ( Canvas 图层栈 | Canvas#saveLayer() 新建图层 | Canvas 状态栈保存信息标志位 )
文章目录
一、Canvas#saveLayer() 新建图层二、Canvas 状态栈保存信息标志位
Canvas 状态保存机制 中 , 存在两个栈结构 , 分别是 状态栈 和 图层栈 ;
其中 图层栈 又称为 Layer 栈 ;
一、Canvas#saveLayer() 新建图层
Canvas 画布类 , 提供了 Canvas#saveLayer()函数 , 用于 创建 新的图层 ;
在自定义组件的 onDraw() 方法中 , 调用 Canvas#saveLayer() 函数 新建图层 完成后 , 后续绘图都是在 新建的图层 中绘制的 , 之前已经绘制的内容不会受到影响 ;
新建图层 只负责将当前图层区域绘制 , 不会干扰其他图层的绘制 ;
Canvas#saveLayer() 函数 相当于创建了一个透明图层 , 之后的绘图操作 , 都在透明图层中执行的 ;
Layer 图层 其在底层也是 由 状态栈 进行保存的 , Canvas#saveLayer() 函数 返回一个 int 类型的返回值 , 这个值是当前的图层对应的 状态栈 索引值 ;
之后调用 Canvas#restoreToCount() 函数 , 传入上述 Canvas#saveLayer() 函数的 int 类型返回值 , 即可使 状态栈 出栈到 该图层对应的 元素 , 即该元素置为栈顶位置 ;
状态栈 中 , 保存的不只是坐标系信息 , 还包括 矩阵信息 , 大小信息 , 图层透明度信息 等 ;
Canvas#saveLayer() 函数原型如下 :
/** * 其行为与save()相同,但除此之外,它还分配和 * 将图形重定向到屏幕外渲染目标。 * 注意:这种方法非常昂贵, * 导致包含内容的呈现成本增加一倍以上。避免 * 在可能的情况下使用此方法,而不是使用 * {@link android.view.view在视图上查看#LAYER_TYPE_HARDWARE HARDWARE LAYER} * 应用xfermode、颜色过滤器或alpha,因为它将执行很多操作 * 比这种方法更好。 *
* 所有图形调用都指向新分配的屏幕外渲染目标。 * 只有在对restore()进行平衡调用时,才是屏幕外的 * 缓冲区拉回到画布的当前目标(可能是前一个 * 层(如果这些调用是嵌套的)。 *
* 绘制的属性{@link Paint#getAlpha()alpha}, * {@link Paint#getXfermode()Xfermode},和 * 当 * 调用restore()时,屏幕外渲染目标会被拉回。 * * @param bounds 可能为空。屏幕外渲染目标需要的最大大小(在局部坐标中) * @param paint 这将被复制,并在调用restore()时应用于屏幕外 * @return 要传递给restoreToccount()以平衡此save()的值 */ public int saveLayer(@android.annotation.Nullable RectF bounds, @android.annotation.Nullable Paint paint) { return saveLayer(bounds, paint, ALL_SAVE_FLAG); }
二、Canvas 状态栈保存信息标志位
MATRIX_SAVE_FLAGCLIP_SAVE_FLAGHAS_ALPHA_LAYER_SAVE_FLAGFULL_COLOR_LAYER_SAVE_FLAGALL_SAVE_FLAG
Canvas 中有如下默认注解 , 该标志位默认为 ALL_SAVE_FLAG , 一般情况下都设置保存所有信息 ;
/** @hide */ @IntDef(flag = true, value = { ALL_SAVE_FLAG }) @Retention(RetentionPolicy.SOURCE) public @interface Saveflags {}
public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint, @Saveflags int saveFlags) { if (bounds == null) { bounds = new RectF(getClipBounds()); } checkValidSaveFlags(saveFlags); return saveLayer(bounds.left, bounds-, bounds.right, bounds.bottom, paint, ALL_SAVE_FLAG); }
保存形式状态位原型 :
// SAVE_FLAG 常数必须与下面定义的值匹配 /** @hide */ @IntDef(flag = true, value = { ALL_SAVE_FLAG }) @Retention(RetentionPolicy.SOURCE) public @interface Saveflags {} /** * 调用Restore()时还原当前矩阵。 * @removed * @deprecated 使用{@link#save()}、{@link#saveLayer(RectF,Paint)}或 * {@link#saveLayerAlpha(RectF,int)}。For saveLayer()调用矩阵 * 始终为{@link#isHardwareAccelerated()硬件加速}还原 * canvas和as的API级别{@value Build.VERSION_代码#O},这是默认值 * 所有画布类型的行为。 */ public static final int MATRIX_SAVE_FLAG = 0x01; /** * 调用Restore()时还原当前剪辑。 * * @removed * @deprecated 使用{@link#save()}、{@link#saveLayer(RectF,Paint)}或 * {@link#saveLayerAlpha(RectF,int)}。For saveLayer()调用剪辑 * 始终为{@link#isHardwareAccelerated()硬件加速}还原 * canvas和as的API级别{@value Build.VERSION_代码#O},这是默认值 * 所有画布类型的行为。 */ public static final int CLIP_SAVE_FLAG = 0x02; /** * 该层需要每像素alpha通道。 * * @removed * @deprecated 忽略此标志。使用{@link#saveLayer(RectF,Paint)}的无标志版本 * {@link#saveLayerAlpha(RectF,int)}。 */ public static final int HAS_ALPHA_LAYER_SAVE_FLAG = 0x04; /** * 该层要求每个颜色通道具有完整的8位精度。 * * @removed * @deprecated 忽略此标志。使用{@link#saveLayer(RectF,Paint)}的无标志版本 * {@link#saveLayerAlpha(RectF,int)}。 */ public static final int FULL_COLOR_LAYER_SAVE_FLAG = 0x08; /** * 将绘图剪切到屏幕外层的边界,忽略此操作将产生后果。 * 注意:强烈建议不要 * 对于任何调用saveLayer()和 * saveLayerAlpha()
变体。一般不通过此标志 * 触发硬件加速渲染的极低性能。 * * @removed * @deprecated 此标志会导致性能较差,使用 * 具有不同剪辑的单个图层或多个绘制命令。 * */ public static final int CLIP_TO_LAYER_SAVE_FLAG = 0x10; /** * 调用Restore()时还原所有内容(标准保存标志)。 * 注:出于性能原因 * 强烈建议将这一整套标志传递给任何 * 调用saveLayer()和saveLayerAlpha() * 变体。 * * 注意:接受此标志的所有方法 * 具有等同于传递此标志的无标志版本。 */ public static final int ALL_SAVE_FLAG = 0x1F;
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~