【问题标题】:Work around Canvas.clipPath() that is not supported in android any more解决 android 不再支持的 Canvas.clipPath()
【发布时间】:2012-01-17 13:46:10
【问题描述】:

从 android 3.0 开始,clipPath() 方法在开启硬件加速的设备中不再受支持。(阅读此article 了解更多详情)。

我正在使用画布,我需要绘制圆形图像。关于如何做到这一点的任何想法?

*我无法关闭硬件加速,我正在寻找其他解决方案。

回答: Tnx @Malcolm 为您解答。我找到了一个很好的例子来演示this technique,它基本上是一个面具。

【问题讨论】:

    标签: android android-canvas hardware-acceleration


    【解决方案1】:

    具有硬件加速的clipPath 仅在 API 级别 18 及更高版本中受支持,在 API 级别从 11 到 17 时需要关闭它。

    你提到的那篇文章有一个线索:

    如果您的应用程序受到任何这些缺失功能或限制的影响,您可以通过调用 setLayerType(View.LAYER_TYPE_SOFTWARE, null) 仅针对应用程序的受影响部分关闭硬件加速。这样,您仍然可以在其他任何地方利用硬件加速。有关如何在应用程序的不同级别启用和禁用硬件加速的更多信息,请参阅Controlling Hardware Acceleration

    这里的主要思想是在应用程序部分禁用硬件加速,您需要在 API 级别低于 18 的设备上使用不受支持的方法。您可以针对特定视图执行此操作,无需转整个应用程序完全关闭。

    如果您不想关闭硬件加速,那么我建议您使用 Porter-Duff 模式。您可以创建一个包含一个圆圈的位图,然后使用这种模式将您的图像绘制到画布上,该模式会将您的图像剪辑到原始内容。

    【讨论】:

    • 是的,但我只有一个视图,(这通常是你在使用画布时得到的......)所以我无法关闭它,这就是为什么我正在寻找解决方案.
    • "不再支持,只是在硬件加速开启的情况下不可用。"这里的双重否定使这句话难以阅读。也许改写为:“clipPath 仅在关闭硬件加速的情况下可用。”
    • @LeoAccend 你为什么不直接suggest an edit自己呢?
    • 谢谢@Malcolm,我没想到我能做到!
    【解决方案2】:

    API 18 起重新引入了对硬件加速的Canvas.clipPath() 支持。

    解决此问题的最佳方法是仅当您在 API 上从 11 运行到 17 时才调用 setLayerType(View.LAYER_TYPE_SOFTWARE, null)

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2
            && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }
    

    我还在 clipPath() 调用周围加上了一个 try-catch 块,以避免意外的应用崩溃:

    if (doClip) {
        try {
            canvas.clipPath(clipPath);
        } catch (UnsupportedOperationException e) {
            Log.e(TAG, "clipPath() not supported");
            doClip = false;
        }
    }
    

    无论如何,不​​应该在 API >= 18 上抛出 UnsupportedOperationException。

    Unsupported Drawing Operations

    【讨论】:

    • 除了提到 API 18 引入了对它的硬件支持之外,这与其他答案中的内容不完全相同吗?当然,应该添加后者。
    • 是的,它是...但是我添加了 API 级别 18 的信息、解释和代码示例...所有这些都在一个简短的答案中。