简单实现控制器过渡动画

自己实现控制器动画的方法,还是比较常见的. 这个是 UINavigationControllerPushDismiss 动画.

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
//
// GUIViewController.m
// GUIControllerTransitionDemo
//
// Created by Kenny on 8/29/15.
// Copyright (c) 2015 Kenny. All rights reserved.
//

#import "GUIViewController.h"
#import "GUIHeader.h"
#import "GUISubViewController.h"
@interface GUIViewController ()
@property(nonatomic,weak)UIButton * pushButton;
@end

@implementation GUIViewController


#pragma mark -life cycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = GUIRandomColor;

[self configPushButton];

}

#pragma mark - delegate

#pragma mark -event response
-(void)pushNewController:(UIButton*)button{

GUISubViewController * subVC = [GUISubViewController new];
[self.navigationController pushViewController:subVC animated:YES];
}
#pragma mark -private methods
-(void)configPushButton{

UIButton * pushButton = [UIButton new];
[pushButton setTitle:@"push new controller button" forState:UIControlStateNormal];
[pushButton setBackgroundColor:GUIRandomColor];
[pushButton addTarget:self action:@selector(pushNewController:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:pushButton];
self.pushButton = pushButton;

}

#pragma mark -getters and setters

#pragma mark - layout method
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];

WSE(ws);
[self.pushButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(GUIScreenWidth, 30));
make.leading.mas_equalTo(ws.view);
make.bottom.mas_equalTo(ws.view).with.offset(-100);
}];

}

@end

然后在 AppDelegate中,为控制器包装一个导航控制器

1
2
3
4
5
6
7
8
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

GUIViewController * vc = [GUIViewController new];
UINavigationController * nav = [[UINavigationController alloc]initWithRootViewController:vc];
[application.delegate window].rootViewController = nav;

return YES;
}

以上纯碎是简单的布局代码,和主题无关.

接下来进入正题:

在Apple的设计中, 实现自定义的切换动画,依赖的是协议中的方法,而不是具体的对象的具体方法,所以我们需要创建一个类

1
2
3
4
5
#import <UIKit/UIKit.h>

@interface GUINavigationControllerDelegate : NSObject<UINavigationControllerDelegate>

@end

.m 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#import "GUINavigationControllerDelegate.h"

@implementation GUINavigationControllerDelegate

/**

当控制器切换的时候被调用,返回一个没有交互性的动画对象
*
* @param navigationController 导航控制器
* @param operation 操作
* @param fromVC 当前控制器
* @param toVC 目标控制器
*
* @return 动画对象
*/

-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{



return nil;
}


@end

描述的非常明确了, 那么现在我们需要一个动画对象,这个对象需要遵守UIViewControllerAnimatedTransitioning协议

1
2
3
4
5
6
7
8
9
10
11
12
13
//
// GUIAnimator.h
// GUIControllerTransitionDemo
//
// Created by Kenny on 8/29/15.
// Copyright (c) 2015 Kenny. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface GUIAnimator : NSObject <UIViewControllerAnimatedTransitioning>

@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
//
// GUIAnimator.m
// GUIControllerTransitionDemo
//
// Created by Kenny on 8/29/15.
// Copyright (c) 2015 Kenny. All rights reserved.
//

#import "GUIAnimator.h"

@implementation GUIAnimator


/**
* 动画执行时间
*
* @param transitionContext 过渡动画上下文环境
*
* @return 动画时长
*/

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 1;
}

/**
* 具体动画行为
*
* @param transitionContext 过渡动画上下文环境
*/

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
//将要切换到的控制器
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
//当前的控制器
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
//container view充当一个虚拟的superView的角色
[[transitionContext containerView] addSubview:toViewController.view];

//设置初始状态
toViewController.view.alpha = 0;

[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
fromViewController.view.transform = CGAffineTransformMakeScale(0.1, 0.1);
toViewController.view.alpha = 1;
} completion:^(BOOL finished) {

fromViewController.view.transform = CGAffineTransformIdentity;

//通知系统,过渡已经完成
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];

}];
}

@end

注释已经写的非常清楚,在此不再赘述.