iOS自定义转场动画(2)——自定义Pop转场动画并加入手势驱动
2015-11-01 09:36
555 查看
自定义Pop转场动画
1、复制PushTransition.h和PushTransition.m。命名为PopTransition.h和PopTransition.m
2、在PopTransition.m中把
ViewController * fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; SecondViewController * toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
改为:
SecondViewController * fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; ViewController * toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
两个类名交换位置即可
3、把所有的avatarImageView改为sourceImageView,把所有的sourceImageView改为avatarImageView,如下:
// 转场动画的具体内容
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
// 获取动画的源控制器和目标控制器
SecondViewController * fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; ViewController * toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView * container = transitionContext.containerView;
// 创建一个imageView的截图,并把原本imageView隐藏,造成以为移动的就是imageView的假象
UIView * snapshotView = [fromVC.avatarImageView snapshotViewAfterScreenUpdates:NO];
snapshotView.frame = [container convertRect:fromVC.avatarImageView.frame fromView:fromVC.view];
fromVC.avatarImageView.hidden = YES;
// 设置目标控制器的位置,并把透明度设为0,在后面的动画中慢慢显示出来变为1
toVC.view.frame = [transitionContext finalFrameForViewController:toVC];
toVC.sourceImageView.hidden = YES;
// 都添加到container中。注意顺序
// [container addSubview:toVC.view];
[container insertSubview:toVC.view belowSubview:fromVC.view];
[container addSubview:snapshotView];
// 执行动画
[UIView animateKeyframesWithDuration:[self transitionDuration:transitionContext] delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
snapshotView.frame = toVC.sourceImageView.frame;
fromVC.view.alpha = 0;
} completion:^(BOOL finished) {
toVC.sourceImageView.hidden = NO;
[snapshotView removeFromSuperview];
fromVC.avatarImageView.hidden = NO;
//一定要记得动画完成后执行此方法,让系统管理 navigation
[transitionContext completeTransition: ![transitionContext transitionWasCancelled]]; // 如果参数写成yes,当用户取消pop时,会继续执行动画,也就是让detailVC消失,设置成这个参数,会避免这样的错误
}];
}
4、修改ViewController中的判断动画类型的方法,加入pop的判断:
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{ if (operation == UINavigationControllerOperationPush){ // 就是在这里判断是哪种动画类型 return [[PushTransition alloc] init]; // 返回push动画的类 }else if (operation == UINavigationControllerOperationPop){ // 就是在这里判断是哪种动画类型 return [[PopTransition alloc] init]; // 返回pop动画的类{ }else{ return nil; } }
系统默认的 Push 和 Pop 动画都支持手势驱动,并且可以根据手势移动距离改变动画完成度。幸运的是,Cocoa 已经集成了相关方法,我们只用告诉它百分比就可以了。所以下一步就是 手势驱动。
1、在 SecondViewController 的 viewDidLoad() 方法中,加入滑动手势。// 加入左侧边界手势 UIScreenEdgePanGestureRecognizer * edgePan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(edgePanGesture:)]; edgePan.edges = UIRectEdgeLeft; [self.view addGestureRecognizer:edgePan];
2、遵循UINavigationControllerDelegate协议,因为navigationController的动画需要在这里执行,所以需要设置代理为自己
- (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; self.navigationController.delegate = self; }
3、在手势监听方法中,创建 UIPercentDrivenInteractiveTransition 属性,并实现手势百分比更新。
// 在手势监听方法中,创建UIPercentDrivenInteractiveTransition属性,并实现手势百分比更新 - (void)edgePanGesture:(UIScreenEdgePanGestureRecognizer *)edgePan{ // 进度值,这是左侧边界的算法,如果要改为右侧边界,改为self.view.bounds.size.width / [edgePan translationInView:self.view].x; CGFloat progress = [edgePan translationInView:self.view].x / self.view.bounds.size.width; if (edgePan.state == UIGestureRecognizerStateBegan) { self.percentDrivenTransition = [[UIPercentDrivenInteractiveTransition alloc] init]; [self.navigationController popViewControllerAnimated:YES]; }else if(edgePan.state == UIGestureRecognizerStateChanged){ [self.percentDrivenTransition updateInteractiveTransition:progress]; }else if(edgePan.state == UIGestureRecognizerStateCancelled || edgePan.state == UIGestureRecognizerStateEnded){ if(progress > 0.5){ [self.percentDrivenTransition finishInteractiveTransition]; }else{ [self.percentDrivenTransition cancelInteractiveTransition]; } self.percentDrivenTransition = nil; } }
4、实现返回 UIViewControllerInteractiveTransitioning 的方法并返回刚刚创建的 UIPercentDrivenInteractiveTransition属性。
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController{ if([animationController isKindOfClass:[PopTransition class]]){ return self.percentDrivenTransition; }else{ return nil; } }
5、还需要设置一下返回动画,否则手势驱动不会生效
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{ if (operation == UINavigationControllerOperationPop){ return [[PopTransition alloc] init]; // 返回pop动画的类 }else{ return nil; } }
完成
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- Gifski:一个跨平台的高质量 GIF 编码器
- 模仿动画的放大缩小容器
- Android中ViewFlipper的使用及设置动画效果实例详解
- jQuery实现美观的多级动画效果菜单代码
- php判断GIF图片是否为动画的方法
- jQuery实现动画效果circle实例
- 浅析JavaScript动画
- js排序动画模拟-插入排序
- javascript+HTML5的Canvas实现Lab单车动画效果
- 基于javascript实现漂亮的页面过渡动画效果附源码下载
- js实现按钮颜色渐变动画效果
- jQuery实现连续动画效果实例分析
- jQuery实现带有洗牌效果的动画分页实例