2012-12-06 59 views
5

UIImageVIewimageView)加入到self.view,捕捉以專輯作品完美:renderInContext不捕獲旋轉子視圖

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的子視圖?

UPDATE:

警告:CALayer的/ -renderInContext:方法沒有實現充分 Core Animation的組合模型。下面提供的代碼將是 能夠解決大多數情況,但有些事情是CALayer/-renderInContext:方法無法正確呈現,因此您可能想要聯繫Developer Technical Support以獲得解決方法請求。

官方Apple技術Q & A QA1703建議聯繫開發者技術支持以獲得解決方法請求。

是否有解決方法已經存在?

回答

5

使用layer.presentationLayer而不是layerrenderInContext

這裏是拍攝的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]; 
1

從文檔:

該方法直接從層樹呈現,忽略添加到呈現樹任何動畫。

您將不得不從表示層讀取旋轉並旋轉圖形上下文。

+0

如何_rotate可識別的圖形context_通過'renderInContext'? – ohho

+0

'CGContextRotateCTM(context,angle)' –

+0

我正在尋找更高級別的屏幕截圖(如power-home組合屏幕截圖)。由於有很多子視圖內部子視圖,它們是由'CABasicAnimation'旋轉的...... – ohho

0

正如David所說,動畫不是由renderInContext呈現的。動畫應用於僅用於顯示的表示層。

最簡單的做法是將您的旋轉應用到CATransaction中的圖層,該圖層會禁用隱式動畫,然後捕獲圖層。

我相信會有效果。 (但是我沒有試過這個具體的東西,所以我不積極。)

或者,你可以設置你的動畫,以便它們在動畫完成後不會設置爲保持有效,而是改變基礎財產權在動畫開始之前。然後,當您渲染圖層時,子圖層應該繪製到最終位置。

渲染一個「飛行中」的動畫會更加棘手。爲此,您需要遍歷圖層樹,查詢每個圖層的表示層,並將您正在設置動畫的設置傳輸到基本圖層。這會在動畫完成後搞砸你的圖層,所以你需要以某種方式保存每個屬性的值,將它設置爲它在表示層的「飛行中」值,捕捉你的圖像,然後設置屬性/每個圖層的屬性返回,全部在禁用動畫的CATransaction內部。

+0

我試過'CATransaction',但沒有運氣。從'CATransaction'文檔中,我的理解是動畫已經被隱式提交(從用戶的角度來看,子視圖是旋轉的,但已經在屏幕上停留了一段時間)。 – ohho

1

您應該可以將renderInContext用於表示層。儘管這可能不適合你走層次結構。因此,它很可能是最簡單的,如果你沒有任何的這些東西:

  • 應用旋轉到所有受影響的子層和渲染根層
  • 寫一個遞歸方法自己手動編寫的表示層