iOS:自定义模态动画 --UIPresentationController
UIPresentationController :展示控制器,是iOS8的一个新特性,用来展示模态窗口的。它是所有模态控制器的管理者。
即:
1> 管理所有Modal出来的控制器
2> 管理所有通过- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion方法显示出来的控制器
3> 管理\监听切换控制器的过程
4> presentingViewController:后面的控制器
5> presentedViewController:前面的控制器
6> presentedView:前面的控制器的view
注意:
1.只要调用了[self presentViewController: animated: completion:]方法
2.首先会创建一个UIPresentationController
3.然后由UIPresentationController管理控制器的切换
拓展:
1、系统给定的集中模态动画展示样式modalPresentationStyle有如下几种:
typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {
UIModalPresentationFullScreen = 0,
UIModalPresentationPageSheet NS_ENUM_AVAILABLE_IOS(3_2),
UIModalPresentationFormSheet NS_ENUM_AVAILABLE_IOS(3_2),
UIModalPresentationCurrentContext NS_ENUM_AVAILABLE_IOS(3_2),
UIModalPresentationCustom NS_ENUM_AVAILABLE_IOS(7_0),
UIModalPresentationOverFullScreen NS_ENUM_AVAILABLE_IOS(8_0),
UIModalPresentationOverCurrentContext NS_ENUM_AVAILABLE_IOS(8_0),
UIModalPresentationPopover NS_ENUM_AVAILABLE_IOS(8_0),
UIModalPresentationNone NS_ENUM_AVAILABLE_IOS(7_0) = -1,
};
2、系统给定的集中模态动画过渡样式modalTransstionStyle有如下几种:
typedef NS_ENUM(NSInteger, UIModalTransitionStyle) {
UIModalTransitionStyleCoverVertical = 0,
UIModalTransitionStyleFlipHorizontal,
UIModalTransitionStyleCrossDissolve,
UIModalTransitionStylePartialCurl NS_ENUM_AVAILABLE_IOS(3_2),
};
由于给定的东西毕竟有限,有的时候不能满足自己需要的动画效果,此时我们可以自己自定义modal动画,做出炫目的动画。
过程:其实做自定义的modal动画还是比较复杂的,因为我既需要自定义动画展示样式类,也需要自定义动画过渡样式类,并且要实现这两个类对应的协议,设置过渡代理,然后实现协议方法。
下面就是具体的实例,自定义modal动画:
导入必要的第三方源文件,方便后面代码的复用
在故事板中设置ViewController控制器的视图颜色
创建一个secondViewController.h/.m/.xib文件,设置视图颜色
创建自定义的动画展示样式类CustomPresentationController.h/.m文件,直接继承自UIPresentationController
.h文件:
#import <UIKit/UIKit.h> @interface CustomPresentationController : UIPresentationController @end
.m文件:重写下面的几个方法
#import "CustomPresentationController.h" @implementation CustomPresentationController //可以改变被模态的控制器视图的尺寸 //- (CGRect)frameOfPresentedViewInContainerView //{ // // /** containerView是容纳presentedView的一个容器 */ // //return CGRectMake(0,50,self.containerView.frame.size.width,self.containerView.frame.size.height-100); // // return CGRectInset(self.containerView.bounds, 0, 50); //} //过渡即将开始时的处理 - (void)presentationTransitionWillBegin { self.presentedView.frame = self.containerView.frame; [self.containerView addSubview:self.presentedView]; } - (void)presentationTransitionDidEnd:(BOOL)completed { } - (void)dismissalTransitionWillBegin { } //过渡消失时的处理 - (void)dismissalTransitionDidEnd:(BOOL)completed { [self.presentedView removeFromSuperview]; } @end
创建自定义的动画过渡样式类CustomAnimationTransition.h/.m文件,实现UIViewControllerAnimatedTransitioning协议
.h文件:
#import <UIKit/UIKit.h> @interface CustomAnimationTransition : NSObject<UIViewControllerAnimatedTransitioning> @property (assign,nonatomic)BOOL presented; @end
.m文件:主要实现下面这两个方法来设置自己需要的动画过渡
#import "CustomAnimationTransition.h" #import "UIView+Extension.h" const CGFloat duration = 1.0f; @implementation CustomAnimationTransition #pragma mark -<UIViewControllerAnimatedTransitioning> //动画时间 - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext { return duration; } //设置过渡动画(modal和dismiss的动画都需要在这里处理) - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext { // UITransitionContextToViewKey, // UITransitionContextFromViewKey. //出来的动画 if (self.presented) { UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey]; //toView.y = -toView.height; //设置动画从上往下进来 toView.x = toView.width; //设置动画从右往左进来 //设置动画3D旋转 //toView.layer.transform = CATransform3DMakeRotation(M_PI_2, 1, 1, 0); [UIView animateWithDuration:duration animations:^{ //toView.y = 0; toView.x = 0; //toView.layer.transform = CATransform3DIdentity; } completion:^(BOOL finished) { //动画完成后,视图上的事件才能处理 [transitionContext completeTransition:YES]; }]; } //销毁的动画 else { [UIView animateWithDuration:duration animations:^{ UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey]; //fromView.y = -fromView.height; fromView.x = -fromView.width; //从右往左出去 //fromView.layer.transform = CATransform3DMakeRotation(M_PI_2, 1, 1, 0); } completion:^(BOOL finished) { //动画完成后,视图上的事件才能处理 [transitionContext completeTransition:YES]; }]; } } @end
创建一个单例的动画类,将ViewController控制器类中实现的UIViewControllerTransitionDelegate协议的方法全部在该类Transition.m文件中实现,主控制器只需要创建这个单例类对象并将它设置为代理即可。
.h文件:
#import <UIKit/UIKit.h> #import "Singleton.h" @interface Transition : NSObject<UIViewControllerTransitioningDelegate> SingletonH(Transition); @end
.m文件:返回动画展示样式和动画过渡样式
#import "Transition.h" #import "CustomPresentationController.h" #import "CustomAnimationTransition.h" @implementation Transition SingletonM(Transition); #pragma mark - <UIViewControllerTransitioningDelegate> //返回展示样式 -(UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source { return [[CustomPresentationController alloc]initWithPresentedViewController:presented presentingViewController:presenting]; } //展示的动画 - (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { CustomAnimationTransition *animation = [[CustomAnimationTransition alloc]init]; animation.presented = YES; return animation; } //关闭时的动画 - (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed { CustomAnimationTransition *animation = [[CustomAnimationTransition alloc]init]; animation.presented = NO; return animation; } @end
在ViewController的.m文件中实现动画测试如下:
#import "ViewController.h" #import "SecondViewController.h" #import "UIView+Extension.h" #import "Transition.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { SecondViewController *second = [[SecondViewController alloc]init]; //设置展示样式(自定义) second.modalPresentationStyle = UIModalPresentationCustom;//设置过渡代理(UIPresentationController) second.transitioningDelegate = [Transition sharedTransition]; [self presentViewController:second animated:YES completion:nil]; } @end
演示结果:从右往左进入,接着往左出去