iOS 7 present/dismiss转场动画
2016-03-31 00:59
405 查看
前言
iOS 7以后提供了自定义转场动画的功能,我们可以通过遵守协议完成自定义转场动画。本篇文章讲解如何实现自定义
present、
dismiss自定义动画。
效果图
本篇文章实现的动画切换效果图如下:视图切换种类
如下效果图,这是有两大类视图切换动画的,一种是交互式的,另一种就是自定义的。本篇只讲其中的
UIViewControllerAnimatedTransitioning协议,来实现
present、
dismiss动画效果。另外的几个,后面会继续学习总结!!!
协议
我们要实现present、
dismiss自定义转场效果,我们必须要有一个遵守了
UIViewControllerAnimatedTransitioning协议且实现其必须实现的代理方法的类。
我们先来学习
UIViewControllerAnimatedTransitioning协议:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @protocol UIViewControllerAnimatedTransitioning <NSObject> // This is used for percent driven interactive transitions, as well as for container // controllers that have companion animations that might need to // synchronize with the main animation. // // 指定转场动画时长,必须实现,否则会Crash。 // 这个方法是为百分比驱动的交互转场和有对比动画效果的容器类控制器而定制的。 - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext; // This method can only be a nop if the transition is interactive // and not a percentDriven interactive transition. // 若非百分比驱动的交互过渡效果,这个方法只能为空 - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext; @optional // This is a convenience and if implemented will be invoked by the system // when the transition context's completeTransition: method is invoked. - (void)animationEnded:(BOOL) transitionCompleted; @end |
UIViewControllerAnimatedTransitioning协议并实现相应的代理方法。
遵守UIViewControllerAnimatedTransitioning协议
下面,我们来定义一个转场类,这个类必须要遵守UIViewControllerAnimatedTransitioning协议,如下:
头文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // // HYBModalTransition.h // PresentDismissTransitionDemo // // Created by huangyibiao on 15/12/21. // Copyright © 2015年 huangyibiao. All rights reserved. // #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> typedef NS_ENUM(NSUInteger, HYBModalTransitionType) { kHYBModalTransitionPresent = 1 << 1, kHYBModalTransitionDismiss = 1 << 2 }; @interface HYBModalTransition : NSObject <UIViewControllerAnimatedTransitioning> /*! * @author 黄仪标, 15-12-21 11:12:44 * * 指定动画类型 * * @param type 动画类型 * @param duration 动画时长 * @param presentHeight 弹出呈现的高度 * @param scale fromVC的绽放系数 * * @return */ + (HYBModalTransition *)transitionWithType:(HYBModalTransitionType)type duration:(NSTimeInterval)duration presentHeight:(CGFloat)presentHeight scale:(CGPoint)scale; @end |
实现文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | // // HYBModalTransition.m // PresentDismissTransitionDemo // // Created by huangyibiao on 15/12/21. // Copyright © 2015年 huangyibiao. All rights reserved. // #import "HYBModalTransition.h" @interface HYBModalTransition () @property (nonatomic, assign) HYBModalTransitionType type; @property (nonatomic, assign) CGFloat presentHeight; @property (nonatomic, assign) CGPoint scale; @property (nonatomic, assign) NSTimeInterval duration; @end @implementation HYBModalTransition + (HYBModalTransition *)transitionWithType:(HYBModalTransitionType)type duration:(NSTimeInterval)duration presentHeight:(CGFloat)presentHeight scale:(CGPoint)scale { HYBModalTransition *transition = [[HYBModalTransition alloc] init]; transition.type = type; transition.presentHeight = presentHeight; transition.scale = scale; transition.duration = duration; return transition; } #pragma mark - UIViewControllerAnimatedTransitioning - (void)animationEnded:(BOOL)transitionCompleted { NSLog(@"%s", __FUNCTION__); } - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext { return self.duration; } - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { switch (self.type) { case kHYBModalTransitionPresent: { [self present:transitionContext]; break; } case kHYBModalTransitionDismiss: { [self dismiss:transitionContext]; break; } default: { break; } } } #pragma mark - Private - (void)present:(id<UIViewControllerContextTransitioning>)transitonContext { UIViewController *fromVC = [transitonContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toVC = [transitonContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView *containerView = [transitonContext containerView]; // 对fromVC.view的截图添加动画效果 UIView *tempView = [fromVC.view snapshotViewAfterScreenUpdates:NO]; tempView.frame = fromVC.view.frame; // 对截图添加动画,则fromVC可以隐藏 fromVC.view.hidden = YES; // 要实现转场,必须加入到containerView中 [containerView addSubview:tempView]; [containerView addSubview:toVC.view]; // 我们要设置外部所传参数 // 设置呈现的高度 toVC.view.frame = CGRectMake(0, containerView.frame.size.height, containerView.frame.size.width, self.presentHeight); // 开始动画 __weak __typeof(self) weakSelf = self; [UIView animateWithDuration:self.duration delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 / 0.5 options:0 animations:^{ // 在Y方向移动指定的高度 toVC.view.transform = CGAffineTransformMakeTranslation(0, -weakSelf.presentHeight); // 让截图缩放 tempView.transform = CGAffineTransformMakeScale(weakSelf.scale.x, weakSelf.scale.y); } completion:^(BOOL finished) { if (finished) { [transitonContext completeTransition:YES]; } }]; } - (void)dismiss:(id<UIViewControllerContextTransitioning>)transitonContext { UIViewController *fromVC = [transitonContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toVC = [transitonContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView *containerView = [transitonContext containerView]; // 取出present时的截图用于动画 UIView *tempView = containerView.subviews.lastObject; // 开始动画 [UIView animateWithDuration:self.duration animations:^{ toVC.view.transform = CGAffineTransformIdentity; fromVC.view.transform = CGAffineTransformIdentity; } completion:^(BOOL finished) { if (finished) { [transitonContext completeTransition:YES]; toVC.view.hidden = NO; // 将截图去掉 [tempView removeFromSuperview]; } }]; } @end |
测试效果
我们要设置一下被present的控制器的代理,在
-viewDidLoad:时添加如下代码:
1 2 3 4 5 | // 配置一下代理防呈现样式为自定义 self.transitioningDelegate = self; self.modalPresentationStyle = UIModalPresentationCustom; |
UIViewControllerTransitioningDelegate,这个是控制器转场动画实现的代理:
1 2 3 4 5 6 7 8 9 10 | #pragma mark - UIViewControllerTransitioningDelegate - (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { return [HYBModalTransition transitionWithType:kHYBModalTransitionPresent duration:0.5 presentHeight:350 scale:CGPointMake(0.9, 0.9)]; } - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed { return [HYBModalTransition transitionWithType:kHYBModalTransitionDismiss duration:0.25 presentHeight:350 scale:CGPointMake(0.9, 0.9)]; } |
present、
dismiss自定义对象,就可以实现我们的动画了。
想要实现什么样的动画,都可以在
HYBModalTransition类里面实现,没有实现不了,只有想不到!!!
相关文章推荐
- iOS7 push/pop转场动画
- iOS9适配
- iOS开发:创建真机调试证书
- iOS Block循环引用
- ios获取文本长度
- ios之无限图片轮播器的实现
- ios 第三方框架
- iOS中的摇一摇功能
- IOS 动画效果
- IOS 动画效果
- IOS开发学习-程序启动原理
- IOS学习 GCD 基础 串行/并行/主线程、同步/异步
- iOS9的僵尸模式设置 NSZombieEnabled
- iOS总结 - Block
- iOS安全些许经验和学习笔记
- iOS开发——CGAffineTransform 详解
- iOS 保持界面流畅的技巧
- OC阅读笔记七:委托数据源与协议
- ios中XMPP的搭建
- ios中XMPP的搭建