本文介绍了带有`Region.Op.REPLACE` 的`canvas.clipRect` 的最佳替代方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我正在开发一个包含大量画布而不是多个视图的库(可用

所以也许它真的没有替代品...

问题

  1. 在这种情况下,最好的选择是什么?
  2. 它究竟为何被弃用?
  3. 与一些已弃用的函数相反,我认为这个函数应该可以安全地继续使用,以防我找不到替代方法,对吗?
解决方案

1: 所有使用自定义 Region.Op 的方法现在都已弃用,因此现在只能使用两种方法变体:clipRect/clipPath(代表 Region.Op.INTERSECT)和 clipOutRect/clipOutPath(代表 Region.Op.DIFFERENCE).要实现类似于Region.Op.REPLACE 的功能,必须使用save()restore() 方法.

所以以前(使用 Op.REPLACE)您只需调用:

canvas.clipRect(0, 0, 100, 100);//做一些剪辑canvas.drawLine(...);//做一些裁剪图canvas.clipRect(200, 200, 400, 400, Region.Op.REPLACE);//将剪切区域替换为完全不同的区域canvas.drawLine(...);//和其他一些绘图

但是现在您必须手动保存和恢复以前的画布状态:

canvas.save();//重要:保存剪辑和矩阵的当前状态(即未剪辑状态)(假设它是状态#1)canvas.clipRect(0, 0, 100, 100);//做一些剪辑canvas.drawLine(...);//做一些裁剪图canvas.restore();//重要提示:回到之前保存(未裁剪)的画布状态(恢复状态 #1)画布.save();//现在再次保存画布的当前状态(剪辑和矩阵)(它是状态 #2)canvas.clipRect(200, 200, 400, 400);//现在我们可以做一些其他的剪辑(就像我们之前用 Region.Op.REPLACE 做的那样)canvas.drawLine(...);//和其他一些绘图canvas.restore();//返回先前保存的状态(到状态 #2)

注意 Canvas 在内部使用堆栈,因此您甚至可以在不同时刻多次调用 save().您调用 canvas.restore() 的次数不能超过调用 canvas.save() 的次数.

另外重要的一点是,调用 canvas.restore() 会改变剪辑矩形(与 canvas.save() 被调用).因此,您必须小心地将 restore() 调用放在所有需要应用裁剪的绘图方法之后.

2:可能是因为一些性能优化.我想我在某处(我现在找不到)读到,对于 GPU 上的硬件加速,他们只能使用 INTERSECT/DIFFERENCE 剪辑操作,而其他操作必须回退到 CPU 处理.这可能就是原因.

这里是一些相关的答案,即由于启用了硬件加速的 ICS 不支持某些 ClipRect 操作.

3:正如他们在文档中所说,它将停止在 Android P 中工作(可能仅在针对 Android P 时):

从 API 级别 API 级别 Build.VERSION_CODES.P 开始,只有 INTERSECT 和 DIFFERENCE 是有效的 Region.Op 参数.

Background

I'm working on a library that has a lot of canvas drawing instead of multiple views (available here).

The problem

As I work to improve it and make it work for our needs of the app (need some customization), I've noticed there are some lines that are marked as deprecated:

canvas.clipRect(0f, mHeaderHeight + mHeaderRowPadding * 2, mHeaderColumnWidth, height.toFloat(), Region.Op.REPLACE)

Thing is, I don't think there is a good candidate to replace this line of code with the newer APIs

What I've found

Looking at the docs, this is what's written:

So I tried using either of those functions, yet both of them caused issues with the drawing of how it used to be.

Looking at the deprecation, it seems that the function itself is marked, but not Region.Op.REPLACE :

So maybe it doesn't really have an alternative...

The questions

  1. What is the best alternative in this case?
  2. Why exactly was it deprecated?
  3. As opposed to some deprecated functions, I assume this one should be safe to still use in case I can't find an alternative, right?
解决方案

1: All methods that use custom Region.Op are deprecated now, so one can use only two method variants now: clipRect/clipPath (which represents Region.Op.INTERSECT) and clipOutRect/clipOutPath (which represents Region.Op.DIFFERENCE). To achieve function similar to Region.Op.REPLACE one must use save() and restore() methods.

So previously (with Op.REPLACE) you would call just:

canvas.clipRect(0, 0, 100, 100); // do some clipping
canvas.drawLine(...); // do some clipped drawing

canvas.clipRect(200, 200, 400, 400, Region.Op.REPLACE); // replace clipping region to completely different one
canvas.drawLine(...); // and some other drawing

But now you have to save and restore previous canvas state manually:

canvas.save();        // IMPORTANT: save current state of clip and matrix (i.e. unclipped state) (let's say it's state #1)
canvas.clipRect(0, 0, 100, 100); // do some clipping
canvas.drawLine(...); // do some clipped drawing
canvas.restore();     // IMPORTANT: get back to previously saved (unclipped) state of the canvas (restores state #1)

canvas.save(); // now save again the current state of canvas (clip and matrix) (it's state #2)
canvas.clipRect(200, 200, 400, 400); // now we can do some other clipping (as we would do with Region.Op.REPLACE before)
canvas.drawLine(...); // and some other drawing
canvas.restore(); // get back go previously saved state (to state #2)

Note Canvas is internally using stack, so you can even call save() multiple times at different moments. You just can't call canvas.restore() more times than the canvas.save() was called.

Also important note is that call to canvas.restore() changes the clip rect (to the same value it was when canvas.save() was called). So you must carefully place the restore() call after all the drawing methods that needs the applied clipping.

2: Probably because of some performance optimizations. I think I read somewhere (I couldn't find it now) that for hardware acceleration on GPU they can use only INTERSECT / DIFFERENCE clip operations and other ones must fall-back to CPU processing. That might be the reason.

EDIT: Here is some related answer, that since ICS with enabled HW acceleration some ClipRect ops are not supported.

3: As they say in documentation, it will stop working in Android P (probably only when targeting Android P):

这篇关于带有`Region.Op.REPLACE` 的`canvas.clipRect` 的最佳替代方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 07:42