2012-12-06 23 views
5

Một UIImageVIew (imageView) sẽ được thêm vào self.view, nắm bắt được cái nhìn vào album hoạt động hoàn hảo:renderInContext không chụp subviews xoay

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); 

Tuy nhiên, nếu subview imageView được quay bởi:

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

Chụp lại self.view không phản ánh vòng quay. Các subview imageView là nếu không quay.

Cách tạo renderInContext hoạt động với các bản xem trước được xoay bởi CABasicAnimation?

UPDATE:

Cảnh báo: CALayer/-renderInContext: phương pháp không thực hiện đầy đủ mô hình thành phần Core Animation. Mã được cung cấp bên dưới sẽ là có thể giải quyết hầu hết các tình huống, nhưng có những thứ mà phương pháp CALayer/-renderInContext: không hiển thị chính xác, vì vậy bạn có thể muốn liên hệ với bộ phận Hỗ trợ kỹ thuật dành cho nhà phát triển để yêu cầu giải pháp.

chính thức của Apple kỹ thuật Q & Một QA1703 đề nghị liên hệ với nhà phát triển Hỗ trợ kỹ thuật cho các yêu cầu khắc phục.

Có cách giải quyết nào đã tồn tại không?

Trả lời

5

Sử dụng layer.presentationLayer thay vì layer khi renderInContext.

Dưới đây là một phạm trù cho việc chụp màn hình của 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 

Cách sử dụng:

UIImage *image = [self.view screenshot:UIDeviceOrientationPortrait 
           isOpaque:YES 
        usePresentationLayer:YES]; 
1

Từ các tài liệu:

Phương pháp này làm cho trực tiếp từ cây lớp, bỏ qua bất kỳ hình ảnh động thêm vào cây render.

Bạn sẽ phải đọc xoay vòng từ lớp trình bày và xoay ngữ cảnh đồ họa.

+0

Làm thế nào để _rotate các context_ đồ họa có thể được công nhận bởi 'renderInContext'? – ohho

+0

'CGContextRotateCTM (ngữ cảnh, góc)' –

+0

Tôi đang tìm một ảnh chụp màn hình ở mức cao hơn (như chụp màn hình kết hợp phím nguồn ở nhà). Vì có nhiều bản xem phụ bên trong các bản xem phụ được xoay vòng bằng 'CABasicAnimation' ... – ohho

0

Như David đã nói, hoạt ảnh không được renderInContext. Ảnh động được áp dụng cho lớp trình bày, chỉ hiển thị.

Điều đơn giản nhất cần thực hiện là áp dụng xoay vòng của bạn cho lớp của bạn bên trong một Giao dịch chuyển hướng vô hiệu hóa hoạt ảnh ngầm, sau đó chụp lớp của bạn.

Tôi tin điều đó sẽ hiệu quả. (Tuy nhiên tôi chưa thử điều cụ thể đó, vì vậy tôi không tích cực.)

Cách khác thuộc tính cơ bản ngay trước khi hoạt ảnh bắt đầu. Sau đó, khi bạn vẽ lớp, các lớp con sẽ vẽ ở vị trí cuối cùng của chúng.

Hiển thị hoạt ảnh "đang bay" sẽ phức tạp hơn nhiều. Cho rằng bạn sẽ cần phải đi bộ cây lớp, truy vấn lớp trình bày của mỗi lớp, và chuyển các thiết lập bạn đang hoạt hình cho lớp cơ sở. Điều đó sẽ làm hỏng các lớp của bạn khi hoạt ảnh hoàn tất tuy nhiên, vì vậy bạn sẽ cần phải tiết kiệm giá trị của mỗi thuộc tính bằng cách nào đó, đặt nó thành giá trị "bay" từ lớp trình bày, chụp ảnh của bạn, sau đó đặt thuộc tính/các thuộc tính của mỗi lớp trở lại, tất cả bên trong một CATransaction sẽ tắt hoạt ảnh.

+0

Tôi đã thử' Giao dịch 'nhưng không có may mắn. Từ tài liệu 'CATransaction', sự hiểu biết của tôi là các hình động đã được cam kết _implicitly_ (từ quan điểm của người dùng, các bản xem phụ được xoay, nhưng đã ở lại trên màn hình một lúc). – ohho

1

Bạn sẽ có thể sử dụng renderInContext với lớp trình bày. Mặc dù điều này có thể không đi bộ phân cấp lớp cho bạn. Vì vậy, nó có lẽ sẽ dễ dàng nhất nếu bạn đã làm một trong những điều sau:

  • áp dụng luân phiên cho tất cả các ảnh hưởng phụ lớp và làm cho lớp rễ
  • viết một phương pháp đệ quy để tự soạn các lớp trình bày bản thân
Các vấn đề liên quan