本篇文章一起来学习iOS 7
以后提供了自定义转场动画的功能,我们可以通过遵守协议完成自定义转场动画。本篇文章讲解如何实现自定义present
、dismiss
自定义动画。
本篇文章实现的动画切换效果图如下:
视图切换种类
如下效果图,这是有两大类视图切换动画的,一种是交互式的,另一种就是自定义的。
本篇只讲其中的UIViewControllerAnimatedTransitioning
协议,来实现present
、dismiss
动画效果。另外的几个,后面会继续学习总结!!!
协议
我们要实现present
、dismiss
自定义转场效果,我们必须要有一个遵守了UIViewControllerAnimatedTransitioning
协议且实现其必须实现的代理方法的类。
我们先来学习UIViewControllerAnimatedTransitioning
协议:
@protocolUIViewControllerAnimatedTransitioning<NSObject> //Thisisusedforpercentdriveninteractivetransitions,aswellasforcontainer //controllersthathavecompanionanimationsthatmightneedto //synchronizewiththemainanimation. // //指定转场动画时长,必须实现,否则会Crash。 //这个方法是为百分比驱动的交互转场和有对比动画效果的容器类控制器而定制的。 -(NSTimeInterval)transitionDuration:(nullableid<UIViewControllerContextTransitioning>)transitionContext; //Thismethodcanonlybeanopifthetransitionisinteractive //andnotapercentDriveninteractivetransition. //若非百分比驱动的交互过渡效果,这个方法只能为空 -(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext; @optional //Thisisaconvenienceandifimplementedwillbeinvokedbythesystem //whenthetransitioncontext'scompleteTransition:methodisinvoked. -(void)animationEnded:(BOOL)transitionCompleted; @end
我们要实现目标效果,就需要一个定义一个类遵守UIViewControllerAnimatedTransitioning
协议并实现相应的代理方法。
遵守协议
下面,我们来定义一个转场类,这个类必须要遵守UIViewControllerAnimatedTransitioning
协议,如下:
头文件
// //HYBModalTransition.h //PresentDismissTransitionDemo // //Createdbyhuangyibiaoon15/12/21. //Copyright©2015年huangyibiao.Allrightsreserved. // #import<Foundation/Foundation.h> #import<UIKit/UIKit.h> typedefNS_ENUM(NSUInteger,HYBModalTransitionType){ kHYBModalTransitionPresent=1<<1, kHYBModalTransitionDismiss=1<<2 }; @interfaceHYBModalTransition:NSObject<UIViewControllerAnimatedTransitioning> /*! *@author黄仪标,15-12-2111:12:44 * *指定动画类型 * *@paramtype动画类型 *@paramduration动画时长 *@parampresentHeight弹出呈现的高度 *@paramscalefromVC的绽放系数 * *@return */ +(HYBModalTransition*)transitionWithType:(HYBModalTransitionType)type duration:(NSTimeInterval)duration presentHeight:(CGFloat)presentHeight scale:(CGPoint)scale; @end
我们只公开了一个方法来创建,指定动画类型,动画时长,呈现的高度,缩放系数。
实现文件
// //HYBModalTransition.m //PresentDismissTransitionDemo // //Createdbyhuangyibiaoon15/12/21. //Copyright©2015年huangyibiao.Allrightsreserved. // #import"HYBModalTransition.h" @interfaceHYBModalTransition() @property(nonatomic,assign)HYBModalTransitionTypetype; @property(nonatomic,assign)CGFloatpresentHeight; @property(nonatomic,assign)CGPointscale; @property(nonatomic,assign)NSTimeIntervalduration; @end @implementationHYBModalTransition +(HYBModalTransition*)transitionWithType:(HYBModalTransitionType)type duration:(NSTimeInterval)duration presentHeight:(CGFloat)presentHeight scale:(CGPoint)scale{ HYBModalTransition*transition=[[HYBModalTransitionalloc]init]; transition.type=type; transition.presentHeight=presentHeight; transition.scale=scale; transition.duration=duration; returntransition; } #pragmamark-UIViewControllerAnimatedTransitioning -(void)animationEnded:(BOOL)transitionCompleted{ NSLog(@"%s",__FUNCTION__); } -(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{ returnself.duration; } -(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{ switch(self.type){ casekHYBModalTransitionPresent:{ [selfpresent:transitionContext]; break; } casekHYBModalTransitionDismiss:{ [selfdismiss:transitionContext]; break; } default:{ break; } } } #pragmamark-Private -(void)present:(id<UIViewControllerContextTransitioning>)transitonContext{ UIViewController*fromVC=[transitonContextviewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController*toVC=[transitonContextviewControllerForKey:UITransitionContextToViewControllerKey]; UIView*containerView=[transitonContextcontainerView]; //对fromVC.view的截图添加动画效果 UIView*tempView=[fromVC.viewsnapshotViewAfterScreenUpdates:NO]; tempView.frame=fromVC.view.frame; //对截图添加动画,则fromVC可以隐藏 fromVC.view.hidden=YES; //要实现转场,必须加入到containerView中 [containerViewaddSubview:tempView]; [containerViewaddSubview:toVC.view]; //我们要设置外部所传参数 //设置呈现的高度 toVC.view.frame=CGRectMake(0, containerView.frame.size.height, containerView.frame.size.width, self.presentHeight); //开始动画 __weak__typeof(self)weakSelf=self; [UIViewanimateWithDuration:self.durationdelay:0.0usingSpringWithDamping:0.5initialSpringVelocity:1.0/0.5options:0animations:^{ //在Y方向移动指定的高度 toVC.view.transform=CGAffineTransformMakeTranslation(0,-weakSelf.presentHeight); //让截图缩放 tempView.transform=CGAffineTransformMakeScale(weakSelf.scale.x,weakSelf.scale.y); }completion:^(BOOLfinished){ if(finished){ [transitonContextcompleteTransition:YES]; } }]; } -(void)dismiss:(id<UIViewControllerContextTransitioning>)transitonContext{ UIViewController*fromVC=[transitonContextviewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController*toVC=[transitonContextviewControllerForKey:UITransitionContextToViewControllerKey]; UIView*containerView=[transitonContextcontainerView]; //取出present时的截图用于动画 UIView*tempView=containerView.subviews.lastObject; //开始动画 [UIViewanimateWithDuration:self.durationanimations:^{ toVC.view.transform=CGAffineTransformIdentity; fromVC.view.transform=CGAffineTransformIdentity; }completion:^(BOOLfinished){ if(finished){ [transitonContextcompleteTransition:YES]; toVC.view.hidden=NO; //将截图去掉 [tempViewremoveFromSuperview]; } }]; } @end
我们这里就不细讲了,因为在iOS 7 push/pop转场动画中已经讲过了。大家若未看过,可以先阅读。
测试效果
我们要设置一下被present
的控制器的代理,在-viewDidLoad:
时添加如下代码:
//配置一下代理防呈现样式为自定义 self.transitioningDelegate=self; self.modalPresentationStyle=UIModalPresentationCustom;
同时,还需要遵守协议并实现协议UIViewControllerTransitioningDelegate
,这个是控制器转场动画实现的代理:
#pragmamark-UIViewControllerTransitioningDelegate -(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController*)presentedpresentingController:(UIViewController*)presentingsourceController:(UIViewController*)source{ return[HYBModalTransitiontransitionWithType:kHYBModalTransitionPresentduration:0.5presentHeight:350scale:CGPointMake(0.9,0.9)]; } -(id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController*)dismissed{ return[HYBModalTransitiontransitionWithType:kHYBModalTransitionDismissduration:0.25presentHeight:350scale:CGPointMake(0.9,0.9)]; }
我们设置present
、dismiss
自定义对象,就可以实现我们的动画了。
想要实现什么样的动画,都可以在HYBModalTransition
类里面实现,没有实现不了,只有想不到!!!
源代码
小伙伴们可以到笔者的github下载:ModalTransitionDemo