
未命名.gif
生成的gif真是不敢恭维,如果读者有比较好的gif生成工具,还望告知与我。
碎片动画的大致原理。
1.返回的时候截取当前屏幕,
2.通过当前截取的视图,来做碎片动画,
思路清晰,直接开搞。这里通过分类方式实现,首先创建分类
46E998A4-C9B0-4EEA-9696-3F71A3FE788D.png
点击Next

4E276709-02D3-48BB-898F-BA8499427E7F.png
命名就随便来了,继续Next创建好我们的分类
这里不得不先说一下,我们需要用到的系统的几个方法

CAF76C39-E654-4866-BAE8-79429EFF785D.png
看不懂的小伙伴自己动手打开Xcode。google翻译一波奥,这里主要说下以上会用到的几个方法
* Creating snapshots from existing snapshots (as a method to duplicate, crop or create a resizable variant)
is supported. In cases where many snapshots are needed, creating a snapshot from a common superview and making subsequent snapshots from it can be more performant.
Please keep in mind that if 'afterUpdates' is YES, the original snapshot is committed and any changes made to it, not the view originally snapshotted, will be included.
*/
- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
以上这个方法就是我们会用到饿截图方法。
- (nullable UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0);
// Resizable snapshots will default to stretching the center
// Use this method to render a snapshot of the view hierarchy into the current context.
Returns NO if the snapshot is missing image data,
YES if the snapshot is complete.
Calling this method from layoutSubviews while the current transaction is committing will capture what is currently displayed regardless if afterUpdates is YES.
resizableSnapshotViewFromRect 这个方法就是根据frame 去截图
到这里,既然我们能根据frame去截图,下边直接进入正题
考虑封装性,外部调用方法,这里直接分类里开出一个方法供外部使用.h代码

90FAFA47-0D81-40D5-8F63-0901403C4C7A.png
/*
pop返回碎片动画
@property 调用示例
[[UIApplication sharedApplication].keyWindow addSubview:self.view];
[self.view fragmenttationAnimation];
[self.navigationController popViewControllerAnimated:NO];
*/
- (void)fragmenttationAnimation;
.m里边实现方法

image.png

image.png
- (void)fragmenttationAnimation{
// 先截图
UIView *snapView = [self snapshotViewAfterScreenUpdates:YES];
// 隐藏容器中的子控件
for (UIView *view in self.subviews) {
view.hidden = YES;
}
//self.backgroundColor = [[UIColor purpleColor]colorWithAlphaComponent:0];
// 保存x坐标的数组
NSMutableArray *xArray = [[NSMutableArray alloc] init];
// 保存y坐标
NSMutableArray *yArray = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < self.bounds.size.width; i = i + 10) {
@autoreleasepool{
[xArray addObject:@(i)];
}
}
for (NSInteger i = 0; i < self.bounds.size.height; i = i + 10) {
@autoreleasepool{
[yArray addObject:@(i)];
}
}
//这个保存所有的碎片
NSMutableArray *snapshots = [[NSMutableArray alloc] init];
for (NSNumber *x in xArray) {
for (NSNumber *y in yArray) {
@autoreleasepool{
CGRect snapshotRegion = CGRectMake([x doubleValue], [y doubleValue], 10, 10);
// resizableSnapshotViewFromRect 这个方法就是根据frame 去截图
UIView *snapshot = [snapView resizableSnapshotViewFromRect:snapshotRegion afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero];
snapshot.frame = snapshotRegion;
[self addSubview:snapshot];
[snapshots addObject:snapshot];
}
}
}
[UIView animateWithDuration:1.5
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
// self.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.05];
for (UIView *view in snapshots) {
@autoreleasepool{
view.frame = CGRectOffset(view.frame, [self randomRange:200 offset:-100], [self randomRange:200 offset:self.frame.size.height/2]);
self.alpha = 0.1;
}
}
}
completion:^(BOOL finished) {
for (UIView *view in snapshots) {
[view removeFromSuperview];
}
[self removeFromSuperview];
}];
}
- (CGFloat)randomRange:(NSInteger)range offset:(NSInteger)offset{
return (CGFloat)(arc4random()%range + offset);
}
代码基本注释都有,有不懂的小伙伴可以私信,或者评论
调用示例
/*
pop返回碎片动画
@property 调用示例
[[UIApplication sharedApplication].keyWindow addSubview:self.view];
[self.view fragmenttationAnimation];
[self.navigationController popViewControllerAnimated:NO];
*/
Demo地址
网友评论