獲取UIView對象的快照
參考
API方法
UIScreen
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates;
UIView
// 獲取當(dāng)前文本的快照視圖
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates;
// 給定一個(gè)可伸縮插值蒋腮,返回基于當(dāng)前視圖的指定內(nèi)容的快照視圖,
- (UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets;
// 將完整視圖層次結(jié)構(gòu)的快照呈現(xiàn)在當(dāng)前上下文中匪蟀。
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates;
Demo 示例
Snapshotting for Animation - 動畫快照
自定義視圖繪制方法:
// 生成旋轉(zhuǎn)視圖
- (void)generateRotations {
for (CGFloat angle = 0; angle < 2 * M_PI; angle += M_PI / 20.0) {
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 250)];
newView.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
newView.layer.borderColor = [UIColor grayColor].CGColor;
newView.layer.borderWidth = 1;
newView.backgroundColor = [UIColor colorWithWhite:0.8 alpha:0.4];
newView.transform = CGAffineTransformMakeRotation(angle);
newView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addSubview:newView];
}
}
重新設(shè)置所有子視圖的背景色:
- (void)recolorSubviews:(UIColor *)newColor {
for (UIView *subview in self.subviews) {
subview.backgroundColor = newColor;
}
}
在動畫中使用UIView快照以簡化復(fù)雜的視圖
#import "ViewController.h"
#import "HQLRotatingViews.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *containerView;
@end
@implementation ViewController {
HQLRotatingViews *_complexView;
}
#pragma mark - Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self createComplexView];
}
#pragma mark - Utility methods
// 向容器視圖中添加旋轉(zhuǎn)視圖
- (void)createComplexView {
_complexView = [[HQLRotatingViews alloc] initWithFrame:self.view.bounds];
[self.containerView addSubview:_complexView];
}
- (void)animateViewAwayAndReset:(UIView *)view {
[UIView animateWithDuration:2.0
animations:^{
view.bounds = CGRectZero;
}
completion:^(BOOL finished) {
// 動畫完成后刪除視圖并創(chuàng)建新視圖
[view removeFromSuperview];
[self performSelector:@selector(createComplexView)
withObject:nil
afterDelay:1];
}];
}
#pragma mark - IBActions
/**
這兩個(gè)方法演示了如何在動畫中使用UIView快照以簡化復(fù)雜的視圖
*/
// ?? Animate 按鈕——直接對 UIView 進(jìn)行旋轉(zhuǎn)
- (IBAction)handleAnimate:(id)sender {
[self animateViewAwayAndReset:_complexView];
}
// ?? 生成當(dāng)前 UIView 的快照之后,對快照進(jìn)行旋轉(zhuǎn)
- (IBAction)handleSnapshot:(id)sender {
// 創(chuàng)建復(fù)合視圖的快照
UIView *snapshotView = [_complexView snapshotViewAfterScreenUpdates:NO];
[self.containerView addSubview:snapshotView];
[_complexView removeFromSuperview];
[self animateViewAwayAndReset:snapshotView];
}
示例一:Animate 按鈕——直接對 UIView 進(jìn)行旋轉(zhuǎn)
示例二:生成當(dāng)前 UIView 的快照之后厦瓢,對快照進(jìn)行旋轉(zhuǎn)
快照方法:
- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates;
測試快照方法中的 BOOL 參數(shù)
/**
這兩種方法比較了是否允許屏幕更新的區(qū)別
- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates;
*/
- (IBAction)handlePreUpdateSnapshot:(id)sender {
// 更新視圖
[_complexView recolorSubviews:[[UIColor redColor] colorWithAlphaComponent:0.3]];
// 創(chuàng)建快照,不等待更改被應(yīng)用。
UIView *snapshotView = [_complexView snapshotViewAfterScreenUpdates:NO];
[self.containerView addSubview:snapshotView];
[_complexView removeFromSuperview];
[self animateViewAwayAndReset:snapshotView];
}
- (IBAction)handlePostUpdateSnapshot:(id)sender {
// 更新視圖
[_complexView recolorSubviews:[[UIColor redColor] colorWithAlphaComponent:0.3]];
// 創(chuàng)建快照舞萄,等待渲染完成恩沽。
UIView *snapshotView = [_complexView snapshotViewAfterScreenUpdates:YES];
[self.containerView addSubview:snapshotView];
[_complexView removeFromSuperview];
[self animateViewAwayAndReset:snapshotView];
}
Pre 按鈕——設(shè)置為 NO
Post 按鈕——設(shè)置為 YES
生成快照圖片
/**
此方法演示了如何向UIView快照添加圖像效果
*/
- (IBAction)handleImageSnapshot:(id)sender {
// 創(chuàng)建一個(gè)圖像上下文 - 復(fù)合視圖的大小和縮放比例
UIGraphicsBeginImageContextWithOptions(_complexView.bounds.size, NO, 0.0);
// 將快照渲染到圖像上下文中
[_complexView drawViewHierarchyInRect:_complexView.bounds afterScreenUpdates:NO];
// 從圖像上下文中抓取圖像
UIImage *complexViewImage = UIGraphicsGetImageFromCurrentImageContext();
// 結(jié)束使用圖像上下文
UIGraphicsEndImageContext();
// 在生成快照之前讓當(dāng)前的視圖模糊化
UIImageView *iv = [[UIImageView alloc] initWithImage:[self applyBlurToImage:complexViewImage]];
iv.center = _complexView.center;
[self.containerView addSubview:iv];
[_complexView removeFromSuperview];
[self performSelector:@selector(animateViewAwayAndReset:)
withObject:iv
afterDelay:1.0];
}
// 模糊化UIImage
- (UIImage *)applyBlurToImage:(UIImage *)image {
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *ci_image = [CIImage imageWithCGImage:image.CGImage];
CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
[filter setValue:ci_image forKey:kCIInputImageKey];
[filter setValue:@5 forKey:kCIInputRadiusKey];
CIImage *result = [filter valueForKey:kCIOutputImageKey];
CGImageRef cgImage = [context createCGImage:result fromRect:[result extent]];
return [UIImage imageWithCGImage:cgImage
scale:image.scale
orientation:image.imageOrientation];
}
Limitaions - 局限性
創(chuàng)建的快照必須在屏幕范圍之內(nèi)