【Android UI】Canvas 画布 ① ( Canvas 状态栈 | Canvas 状态栈入栈与出栈 | 获取 Canvas 状态栈容量 | Canvas 状态栈原点数据 )

2023-03-30 16:03:30 浏览数 (2)

文章目录

  • 一、Canvas 状态栈入栈与出栈
  • 二、获取 Canvas 状态栈容量
  • 三、Canvas 状态栈原点数据

Canvas 状态保存机制 中 , 存在两个栈结构 , 分别是 状态栈 和 图层栈 ;

其中 图层栈 又称为 Layer 栈 ;

一、Canvas 状态栈入栈与出栈


状态栈 用于保存 绘图坐标系 信息 ,

  • 每次调用 Canvas#save() 方法 , 都会向 状态栈 中存储一份坐标数据 , 即 入栈操作 , 状态栈 是 后入先出 的栈结构 数据 ;
  • 每次调用 Canvas#restore() 方法 , 就是将 状态栈 栈顶的坐标数据 , 进行 出栈操作 ;

Canvas#save() 方法函数原型 :

代码语言:javascript复制
    /**
     * 保存当前矩阵并将其剪辑到私有堆栈上。
     * 
     * 随后对translate、scale、rotate、skew、concat或clipRect、clipPath的调用都将照常运行,
     * 但当对restore()进行平衡调用时,这些调用将被忘记,并且将恢复save()之前存在的设置。
     *
     * @return 传递给restoreToCount()以平衡此save()的值
     */
    public int save() {
        return nSave(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
    }

Canvas#restore() 方法函数原型 :

代码语言:javascript复制
    /**
     * 此调用平衡了之前对save()的调用,并用于删除自上次save调用以来对矩阵/片段状态的所有修改。
     * 调用restore()的次数比调用save()的次数多是错误的。
     */
    public void restore() {
        if (!nRestore(mNativeCanvasWrapper)
                && (!sCompatibilityRestore || !isHardwareAccelerated())) {
            throw new IllegalStateException("Underflow in restore - more restores than saves");
        }
    }

二、获取 Canvas 状态栈容量


通过调用 Canvas#getSaveCount() 方法 , 可以 获取当前 Canvas 画布的 状态栈 容量 , 当前缓存了多少个 坐标数据 , 也就是调用了多少次 Canvas#save() 方法 ;

Canvas#getSaveCount() 函数原型 :

代码语言:javascript复制
    /**
     * 返回画布私有堆栈上的矩阵/剪辑状态数。
     * 这将等于#save()调用-#restore()调用。
     */
    public int getSaveCount() {
        return nGetSaveCount(mNativeCanvasWrapper);
    }

三、Canvas 状态栈原点数据


Canvas 的 状态栈 中, 默认存在一个数据 , 就是 原点 坐标数据 , 也就是即使不调用 Canvas#save() 方法 , 直接调用 Canvas#getSaveCount() 方法获取的值是 1 ;

如果没有调用 Canvas#save() 方法 , 直接调用 Canvas#restore() 方法 , 就会将 状态栈 中的 原点坐标数据 出栈 , 该操作会导致程序崩溃 , 崩溃信息如下 :

代码语言:javascript复制
2022-07-05 18:08:53.073 22010-22010/kim.hsl.android_ui E/AndroidRuntime: FATAL EXCEPTION: main
    Process: kim.hsl.android_ui, PID: 22010
    java.lang.IllegalStateException: Underflow in restore - more restores than saves
        at android.graphics.Canvas.restore(Canvas.java:605)
        at kim.hsl.android_ui.PathMeasureView3.onDraw(PathMeasureView3.java:38)
        at android.view.View.draw(View.java:20207)

0 人点赞