iOS7中的ViewController切换
实现控制器之间的切换:(实现弹跳的效果:)
先实现一个自定义的类似的modal present的效果,与普通效果不同的是,我们希望modalVC出现的时候不要那么乏味的就简单从底部出现,而是带有一个弹性效果:
ViewController的实现:
1 // 2 // ViewController.m 3 // ViewController切换 4 // 5 // Created by 思 彭 on 16/3/29. 6 // Copyright © 2016年 combanc. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import "ModalViewController.h" 11 #import "BouncePresentAnimation.h" 12 13 14 15 @interface ViewController ()<ModalViewControllerDelegate,UIViewControllerTransitioningDelegate> 16 17 @property (nonatomic, strong) BouncePresentAnimation *presentAnimation; 18 19 20 @end 21 22 @implementation ViewController 23 24 25 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 26 { 27 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 28 if (self) { 29 30 _presentAnimation = [BouncePresentAnimation new]; 31 32 } 33 return self; 34 } 35 36 37 38 - (void)viewDidLoad { 39 [super viewDidLoad]; 40 self.view.backgroundColor = [UIColor lightGrayColor]; 41 42 UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 43 button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0); 44 button.backgroundColor = [UIColor redColor]; 45 [button setTitle:@"Dismiss me" forState:UIControlStateNormal]; 46 [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; 47 [self.view addSubview:button]; 48 49 50 } 51 52 53 // 按钮点击触发方法 54 55 -(void) buttonClicked:(id)sender 56 { 57 ModalViewController *mvc = [[ModalViewController alloc] init]; 58 59 mvc.delegate = self; 60 mvc.transitioningDelegate = self; 61 62 //模态到ModalViewController 63 [self presentViewController:mvc animated:YES completion:nil]; 64 } 65 66 67 //实现协议方法 68 69 -(void)modalViewControllerDidClickedDismissButton:(ModalViewController *)viewController 70 { 71 [self dismissViewControllerAnimated:YES completion:nil]; 72 } 73 74 75 76 - (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source 77 { 78 return self.presentAnimation; 79 } 80 81 82 83 84 - (void)didReceiveMemoryWarning { 85 [super didReceiveMemoryWarning]; 86 // Dispose of any resources that can be recreated. 87 } 88 89 @end
ModalViewController的实现:
1 #import <UIKit/UIKit.h> 2 3 @class ModalViewController; 4 5 @protocol ModalViewControllerDelegate<NSObject> 6 7 8 -(void) modalViewControllerDidClickedDismissButton:(ModalViewController *)viewController; 9 10 11 @end 12 13 14 @interface ModalViewController : UIViewController 15 16 @property (nonatomic, weak) id<ModalViewControllerDelegate> delegate; 17 18 @end
1 // 2 // ModalViewController.m 3 // ViewController切换 4 // 5 // Created by 思 彭 on 16/3/29. 6 // Copyright © 2016年 combanc. All rights reserved. 7 // 8 9 #import "ModalViewController.h" 10 11 @implementation ModalViewController 12 13 14 - (void)viewDidLoad{ 15 16 [super viewDidLoad]; 17 18 // Do any additional setup after loading the view. 19 self.view.backgroundColor = [UIColor grayColor]; 20 21 UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 22 button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0); 23 button.backgroundColor = [UIColor greenColor]; 24 [button setTitle:@"Dismiss me" forState:UIControlStateNormal]; 25 [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; 26 [self.view addSubview:button]; 27 28 } 29 30 // 按钮点击触发方法 31 32 -(void) buttonClicked:(id)sender 33 { 34 if (self.delegate && [self.delegate respondsToSelector:@selector(modalViewControllerDidClickedDismissButton:)]) { 35 [self.delegate modalViewControllerDidClickedDismissButton:self]; 36 } 37 } 38 39 40 41 @end
BouncePresentAnimation的代码实现:
1 #import <Foundation/Foundation.h> 2 #import <UIKit/UIKit.h> 3 4 5 // 在遵守协议UIViewControllerAnimatedTransitioning记得导入UIKit框架 6 7 @interface BouncePresentAnimation : NSObject<UIViewControllerAnimatedTransitioning> 8 9 10 @end
1 // 2 // BouncePresentAnimation.m 3 // ViewController切换 4 // 5 // Created by 思 彭 on 16/3/29. 6 // Copyright © 2016年 combanc. All rights reserved. 7 // 8 9 #import "BouncePresentAnimation.h" 10 11 @implementation BouncePresentAnimation 12 13 14 15 #pragma mark - UIViewControllerAnimatedTransitioning代理 16 17 - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{ 18 19 return .6f; 20 21 22 } 23 24 25 - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{ 26 27 // 1. Get controllers from transition context 28 UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 29 30 // 2. Set init frame for toVC 31 CGRect screenBounds = [[UIScreen mainScreen] bounds]; 32 CGRect finalFrame = [transitionContext finalFrameForViewController:toVC]; 33 toVC.view.frame = CGRectOffset(finalFrame, 0, screenBounds.size.height); 34 35 // 3. Add toVC's view to containerView 36 UIView *containerView = [transitionContext containerView]; 37 [containerView addSubview:toVC.view]; 38 39 // 4. Do animate now 40 NSTimeInterval duration = [self transitionDuration:transitionContext]; 41 [UIView animateWithDuration:duration 42 delay:0.0 43 usingSpringWithDamping:0.6 44 initialSpringVelocity:0.0 45 options:UIViewAnimationOptionCurveLinear 46 animations:^{ 47 toVC.view.frame = finalFrame; 48 } completion:^(BOOL finished) { 49 // 5. Tell context that we completed. 50 [transitionContext completeTransition:YES]; 51 }]; 52 53 54 } 55 56 57 @end
解释一下这个实现:
1.我们首先需要得到参与切换的两个ViewController的信息,使用context的方法拿到它们的参照;
2.对于要呈现的VC,我们希望它从屏幕下方出现,因此将初始位置设置到屏幕下边缘;
3.将view添加到containerView中;
4.开始动画。这里的动画时间长度和切换时间长度一致,都为0.8s。usingSpringWithDamping的UIView动画API是iOS7新加入的,描述了一个模拟弹簧动作的动画曲线,我们在这里只做使用,更多信息可以参看相关文档;(顺便多说一句,iOS7中对UIView动画添加了一个很方便的Category,UIViewKeyframeAnimations。使用其中方法可以为UIView动画添加关键帧动画)
5.在动画结束后我们必须向context报告VC切换完成,是否成功(在这里的动画切换中,没有失败的可能性,因此直接pass一个YES过去)。系统在接收到这个消息后,将对VC状态进行维护。