方法snapshotViewAfterScreenUpdates 简单介绍
1. 方法的由来
在iOS7 以前, 获取一个UIView的快照有以下步骤: 首先创建一个UIGraphics的图像上下文,然后将视图的layer渲染到该上下文中,从而取得一个图像,最后关闭图像上下文,并将图像显示在UIImageView中。
现在我们只需要一行代码就可以完成上述步骤了:
[view snapshotViewAfterScreenUpdates:NO];
这个方法制作了一个UIView的副本,如果我们希望视图在执行动画之前保存现在的外观,以备之后使用(动画中视图可能会被子视图遮盖或者发生其他一些变化),该方法就特别方便。
2. 注意事项
afterUpdates参数表示是否在所有效果应用在视图上了以后再获取快照。例如,如果该参数为NO,则立马获取该视图现在状态的快照,反之,以下代码只能得到一个空白快照:
[view snapshotViewAfterScreenUpdates:YES];
[view setAlpha:0.0];
由于我们设置afterUpdates参数为YES,而视图的透明度值被设置成了0,所以方法将在该设置应用在视图上了之后才进行快照,于是乎屏幕空空如也。另外就是……你可以对快照再进行快照……继续快照……
snapshotViewAfterScreenUpdates:方法失效的解决办法
iOS7之后,使用snapshotViewAfterScreenUpdates:方法可以轻松的获取某个控件的截图,在iPhone7和7Plus中该方法失效,可以用下面的方法:
- (UIImageView*)imageFromView:(UIView*)snapView {
UIGraphicsBeginImageContextWithOptions(snapView.frame.size, NO, 0.0);
CGContextRefcontext =UIGraphicsGetCurrentContext();
[snapView.layerrenderInContext:context];
UIImage*targetImage =UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView*imageView = [[UIImageViewalloc]initWithImage:targetImage];
imageView.frame= snapView.frame;
returnimageView;
}
UIGraphicsBeginImageContextWithOptions中的第三个参数设置为0.0时,获取的图片较为清晰,如果设置>0时,会有模糊效果。
示例代码:
参考: http://www.jianshu.com/p/7cdabe568830
使用案例:
如果你是一个电商项目,将商品加入购物车,这个动画就可以用这个来实现(Ps:我记得京东还是淘宝久有这个效果,但是我却又找不到了),点击加入购物车,然后对商品生成一个快照,然后缩小移动到购物车(还可以加入旋转的动画),到购物车的位置,移除。Perfect!
原文作者的项目,读信的过程--点击信封,然后生成快照,然后快照位移到屏幕中间,消失,然后信封详情出现。
实现
首先,定义动画效果的实现:
查看信件:
a.点击信件,然后生成信件快照;
b.信件快照位移到屏幕中央;同时信件详情出现,信件快照消失;
关闭详情:
a.点击空白处,生成信件详情快照和信件快照;信件快照起始状态隐藏;
b.信件详情快照慢慢变小到和信件快照同样大小;然后消失,信件快照显示;
c:信件快照位移到信件的位置,然后消失;
注意事项:
如果是iOS7之后--iOS10之前:
- (UIView *)customSnapshotFromView:(UIView *)inputView {
UIView *snapshot = [inputView snapshotViewAfterScreenUpdates:YES];
snapshot.layer.masksToBounds = YES;
snapshot.layer.cornerRadius = 0.0;
snapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0);
snapshot.layer.shadowRadius = 5.0;
snapshot.layer.shadowOpacity = 0.4;
return snapshot;
}
如果是iOS10之后:
- (UIView *)customSnapshotFromView:(UIView *)inputView {
UIGraphicsBeginImageContextWithOptions(inputView.frame.size, NO, 0.0);
CGContextRef context =UIGraphicsGetCurrentContext();
[inputView.layer renderInContext:context];
UIImage*targetImage =UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView*imageView = [[UIImageView alloc]initWithImage:targetImage];
imageView.frame= inputView.frame;
return imageView;
}