【问题标题】:How could I trick [CALayer renderInContext: ] to render only a section of the layer?我怎么能欺骗 [CALayer renderInContext: ] 只渲染图层的一部分?
【发布时间】:2013-01-05 11:13:07
【问题描述】:

我很清楚,除了渲染整个视图和裁剪之外,没有很好的方法可以将 UIView 的一小部分渲染到图像上。 (在 iPad 3 之类的设备上非常昂贵,生成的图像很大)。有关 renderInContext 方法的描述,请参见 here(没有其他选择)。

我要渲染的视图部分无法预先确定,这意味着我无法将小部分的视图层次结构设置为它自己的 UIView(因此是 CALayer)。

我的想法...

我有一个想法,但如果我要成功,我需要一些指导。如果我在 UIView(或 CALayer)上创建一个类别,该类别添加一个方法如下:

[UIView renderSubframe:(CGFrame)frame];

怎么样?好吧,我在想,如果创建了一个子框架大小的虚拟视图,那么视图可以暂时转移到这个上。然后虚拟视图的层可以调用 renderInContext:,从而获得一种高效且快速的视图。

所以...

我真的不太了解 CALayer/Quartz 核心的东西……这有可能奏效吗?如果没有,还有什么方法可以达到同样的效果 - 我可以达到相同结果的最有效方法是什么(或者其他人已经面临这个问题并提出不同的解决方案)?

【问题讨论】:

    标签: iphone objective-c ios ipad calayer


    【解决方案1】:

    这是我最终写的类别。多亏了方便的 CGAffineTransform,没有我最初想的那么难。

    #import "UIView+RenderSubframe.h"
    #import <QuartzCore/QuartzCore.h>
    
    @implementation UIView (RenderSubframe)
    
    - (UIImage *) renderWithBounds:(CGRect)frame {
    
        CGSize imageSize = frame.size;
    
        UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
        CGContextRef c = UIGraphicsGetCurrentContext();
    
        CGContextConcatCTM(c, CGAffineTransformMakeTranslation(-frame.origin.x, -frame.origin.y));
        [self.layer renderInContext:c];
    
        UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return screenshot;
    
    }
    
    @end
    

    【讨论】:

    • 我已经对此进行了测试,看来渲染操作在图层上调用的 drawRect 仍在绘制到完整大小的上下文中。
    • @Plenilune 使用仪器进行测试显示,当使用小于视图的帧调用它时,内存使用量要少得多。在我的例子中,框架是屏幕大小的,而不是视图大小(它是屏幕大小的 3 倍)。
    • 我想补充一点,这个类别工作得很好,但有一种情况是它没有渲染我拥有的 UIImage 动画,结果证明将其更改为 [self.layer.presentationLayer renderInContext:c]; 是解决方案!
    【解决方案2】:

    您可以通过几种不同的方式来做到这一点:

    1. 在调用 renderInContext 之前为您的上下文指定 CGContextClipToRect

    2. 使用:

    setNeedsDisplayInRect:

    将指定矩形内的区域标记为需要更新。

         - (void)setNeedsDisplayInRect:(CGRect)theRect
    

    这将使渲染仅在指定的矩形中发生。我不确定这是否符合您的要求。

    我认为第一个选项应该可以无缝运行。

    【讨论】:

    • 我可能错了,但选项 2 可能会导致生成大图像(即使其中一些可能是空白的)? renderInContext 调用的许多开销似乎是它创建的图像的大小,导致很快需要大量内存。选项 1 绝对有潜力 - 将首先尝试这个!
    • 不幸的是,CGContextClipToRect 将图像保留为大(大部分是透明的)图像,它仅在帧原点为 0,0 时才真正起作用。不过,您让我走上了正确的道路,这让我找到了一个简单的解决方案!
    • 愿意分享解决方案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    • 2017-03-26
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多