关于转场动画的切换这方便一直想研究好久了,但是奈何都下不了决心,
http://blog.csdn.net/hmt20130412/article/details/39079905 这篇博客对于转场动画,我认为讲解得比较详细了
在iOS7中,苹果官方提供了几个关键性的API,我这边再次简单总结下
1.在我们做转场动画的时候,需要实现几个代理
A.动画控制器 (Animation Controllers) 遵从 UIViewControllerAnimatedTransitioning 协议,并且负责实际执行动画。
B.交互控制器 (Interaction Controllers) 通过遵从 UIViewControllerInteractiveTransitioning 协议来控制可交互式的转场《暂时先不做》。
//我这边就直接上例子,定义一个动画继承自NSObject,实现代理UIViewControllerAnimatedTransitioning
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, AnimationType) {
AnimationTypePush,
AnimationTypePop,
};
@interface ChangeVCAnimationDele : NSObject<UIViewControllerAnimatedTransitioning>
@property (nonatomic,assign)AnimationType actionType; /**< 当前的动画是push还是pop*/
@property (nonatomic,assign)CGPoint center;/**< 消失,显示的中心点*/
@end
.h文件
#import "ChangeVCAnimationDele.h"
#define kAnimtionTime 0.5f
@interface ChangeVCAnimationDele ()
@property (nonatomic,strong)CAShapeLayer *maskLayer;
@property (nonatomic,strong)id<UIViewControllerContextTransitioning> transitionContext;
@property (nonatomic,weak)UIViewController *toVC;/**< 目标的VC*/
@property (nonatomic,weak)UIViewController *fromeVC; /**< 来源的VC*/
@end
@implementation ChangeVCAnimationDele
- (CAShapeLayer *)maskLayer {
if (!_maskLayer) {
_maskLayer = [[CAShapeLayer alloc] init];
}
return _maskLayer;
}
// 系统给出一个切换上下文,我们根据上下文环境返回这个切换所需要的花费时间
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return kAnimtionTime;
}
// 完成容器转场动画的主要方法,我们对于切换时的UIView的设置和动画都在这个方法中完成
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
// 可以看做为destination ViewController 目标VC
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// 可以看做为source ViewController
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
self.toVC = toViewController;
self.fromeVC = fromViewController;
self.transitionContext = transitionContext;
if (AnimationTypePush == self.actionType) {
[[transitionContext containerView] addSubview:toViewController.view];
//防止闪动,需要提前处理动画结束的代码
[NSTimer scheduledTimerWithTimeInterval:kAnimtionTime target:self selector:@selector(animationFinish:) userInfo:nil repeats:NO];
[self show];
}
else {
[[transitionContext containerView] addSubview:toViewController.view];
[[transitionContext containerView] addSubview:fromViewController.view];
[self dismiss];
}
}
- (UIBezierPath *)bezierPathWithCenter:(CGPoint)center Radius:(CGFloat)radius {
CGRect rect = CGRectMake(center.x - radius, center.y - radius, radius * 2, radius * 2);
return [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
}
#pragma mark -
#pragma mark - push
- (void)show {
self.toVC.view.layer.mask = self.maskLayer;
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
pathAnimation.fromValue = (__bridge id _Nullable)([self bezierPathWithCenter:self.center Radius:0].CGPath);
pathAnimation.toValue = (__bridge id _Nullable)([self bezierPathWithCenter:self.center Radius:1000].CGPath);
pathAnimation.duration = kAnimtionTime + 0.1;
// pathAnimation.delegate = self;
pathAnimation.removedOnCompletion = YES;
[self.maskLayer addAnimation:pathAnimation forKey:@"show"];
}
#pragma mark -
#pragma mark - POP
- (void)dismiss {
self.fromeVC.view.layer.mask = self.maskLayer;
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
pathAnimation.fromValue = (__bridge id _Nullable)([self bezierPathWithCenter:_center Radius:1000].CGPath);
pathAnimation.toValue = (__bridge id _Nullable)([self bezierPathWithCenter:_center Radius:0].CGPath);
pathAnimation.duration = kAnimtionTime;
pathAnimation.delegate = self;
pathAnimation.removedOnCompletion = YES;
[self.maskLayer addAnimation:pathAnimation forKey:@"dismiss"];
}
#pragma mark -
#pragma mark - 时间差,这个时候等动画完成了,中间需要一段时间才会执行代理,所以在push的时候需要提前处理操作,pop的时候需要延后处理,也就不要写计时器的
//pop的时候用到
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
if (flag) {
[self.fromeVC.view removeFromSuperview];
[self.transitionContext completeTransition:![self.transitionContext transitionWasCancelled]];
self.toVC.view.layer.mask = nil;
}
}
//push的时候用到
- (void)animationFinish:(NSTimer *)timer {
[self.transitionContext completeTransition:![self.transitionContext transitionWasCancelled]];
self.toVC.view.layer.mask = nil;
}
@end
.m文件
到此时,基本动画已经完成了,最后就是在适当的时候插入动画了,来到push的VC
定义Navigation的代理《我这里只做了push的,present是一样的》
self.navigationController.delegate = self;
然后实现Navigation的代理
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC {
ChangeVCAnimationDele *animation = [[ChangeVCAnimationDele alloc]init];
if (operation == UINavigationControllerOperationPush) {
animation.actionType = AnimationTypePush;
}else {
animation.actionType = AnimationTypePop;
}
animation.center = self.customBtn.center;
return animation;
}