6

A UIImageVIew( imageView) 被添加到self.view,完美地捕捉到相册的视图:

 CGSize size = CGSizeMake(self.view.frame.size.height, self.view.frame.size.width);
 UIGraphicsBeginImageContext(size);
 [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
 UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();
 UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);

但是,如果imageView子视图旋转:

 [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

再次捕获self.view不会反映旋转。子视图imageView好像没有旋转。

如何renderInContext使用旋转的子视图制作作品CABasicAnimation

更新:

警告:CALayer/-renderInContext: 方法没有实现完整的核心动画合成模型。下面提供的代码将能够解决大多数情况,但是 CALayer/-renderInContext: 方法无法正确呈现某些情况,因此您可能希望联系开发人员技术支持以获取解决方法请求。

官方 Apple 技术问答QA1703建议联系开发人员技术支持以获取解决方法请求。

是否已经存在解决方法?

4

4 回答 4

5

使用layer.presentationLayer而不是layerwhen renderInContext

这是一个用于截取UIView的类别,UIView+Screenshot.h:

 //
 //  UIView+Screenshot.h
 //
 //  Created by Horace Ho on 2012/12/11.
 //  Copyright (c) 2012 Horace Ho. All rights reserved.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
 //
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
 //
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.

 @interface UIView (HHScreenShot)
 - (UIImage *)screenshot:(UIDeviceOrientation)orientation isOpaque:(BOOL)isOpaque usePresentationLayer:(BOOL)usePresentationLayer;
 @end

 @implementation UIView (HHScreenShot)

 - (UIImage *)screenshot:(UIDeviceOrientation)orientation isOpaque:(BOOL)isOpaque usePresentationLayer:(BOOL)usePresentationLayer
 {
     CGSize size;

     if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown) {
         size = CGSizeMake(self.frame.size.width, self.frame.size.height);
     } else {
         size = CGSizeMake(self.frame.size.height, self.frame.size.width);
     }

     UIGraphicsBeginImageContextWithOptions(size, isOpaque, 0.0);

     if (usePresentationLayer) {
         [self.layer.presentationLayer renderInContext:UIGraphicsGetCurrentContext()];
     } else {
         [self.layer renderInContext:UIGraphicsGetCurrentContext()];
     }

     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

     UIGraphicsEndImageContext();

     return image;
 }

 @end

要使用:

 UIImage *image = [self.view screenshot:UIDeviceOrientationPortrait
                               isOpaque:YES 
                   usePresentationLayer:YES];
于 2012-12-11T04:44:23.867 回答
2

从文档中:

此方法直接从层树渲染,忽略添加到渲染树的任何动画。

您必须从表示层读取旋转并旋转图形上下文。

于 2012-12-06T13:13:23.730 回答
2

您应该能够将 renderInContext 与表示层一起使用。尽管这可能不会为您遍历层层次结构。因此,如果您执行以下任何一项操作,这可能是最简单的:

  • 将旋转应用于所有受影响的子层并渲染根层
  • 编写一个递归方法来自己手动组合表示层
于 2012-12-10T09:37:52.410 回答
1

正如大卫所说,动画不是由 renderInContext 渲染的。动画应用于仅显示的表示层。

最简单的做法是将旋转应用于禁用隐式动画的 CATransaction 内的图层,然后捕获您的图层。

我相信这会奏效。(但是我没有尝试过那个具体的东西,所以我不是很积极。)

或者,您可以设置动画,以便在动画完成后它们不会保持有效,而是在动画开始之前更改基础属性。然后,当您渲染图层时,子图层应绘制在它们的最终位置。

渲染“飞行中”动画会更加棘手。为此,您需要遍历层树,查询每个层的表示层,并将您正在制作动画的设置传输到基础层。但是,一旦动画完成,这会搞砸您的图层,因此您需要以某种方式保存每个属性的值,将其设置为表示层的“飞行中”值,捕获图像,然后设置属性/每个图层的属性,都在禁用动画的 CATransaction 中。

于 2012-12-07T02:05:36.083 回答