先寫(xiě)一些通用部分
實(shí)現(xiàn)協(xié)議
在要添加自定義效果的視圖控制器中實(shí)現(xiàn)代理協(xié)議UINavigationControllerDelegate
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.navigationController.delegate = self;
}
實(shí)現(xiàn)代理方法
#pragma mark -UINavigationControllerDelegate
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
if (operation == UINavigationControllerOperationPush) {
//返回我們自定義的效果
return [[PushTransition alloc]init];
}
else if (operation == UINavigationControllerOperationPop){
return [[PopTransition alloc]init];
}
//返回nil則使用默認(rèn)的動(dòng)畫(huà)效果
return nil;
}
注:PushTransition拙绊、PopTransition為具體效果的實(shí)現(xiàn)
PushTransition的實(shí)現(xiàn)
這種效果的實(shí)現(xiàn)類需要實(shí)現(xiàn)UIViewControllerAnimatedTransitioning
協(xié)議
通用代碼部分
//.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface PushTransition : NSObject<UIViewControllerAnimatedTransitioning>
@end
//.m
#import "PushTransition.h"
@interface PushTransition ()
@end
@implementation PushTransition
// This is used for percent driven interactive transitions, as well as for container controllers that have companion animations that might need to
// synchronize with the main animation.
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext
{
//返回動(dòng)畫(huà)的執(zhí)行時(shí)間
return 1.0f;
}
// This method can only be a nop if the transition is interactive and not a percentDriven interactive transition.
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
self.transitionContext = transitionContext;
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
//不添加的話唯欣,屏幕什么都沒(méi)有
UIView *containerView = [transitionContext containerView];
[containerView addSubview:fromVC.view];
[containerView addSubview:toVC.view];
//注意注意一定要注意這里熊经。我們就是在這里添加我們所需要的動(dòng)畫(huà)效果。將動(dòng)畫(huà)效果的代碼放在這里就行了圆存。重要的事情要說(shuō)好幾遍
//如果取消了就設(shè)置為NO仪糖,反之找前,設(shè)置為YES栏妖。如果添加了動(dòng)畫(huà),這句代碼在動(dòng)畫(huà)結(jié)束之后再調(diào)用
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}
實(shí)例程序一
實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的扇形動(dòng)畫(huà)
//.m
#import "PushTransition.h"
@interface PushTransition ()
@property(nonatomic,strong) id<UIViewControllerContextTransitioning>transitionContext;
@end
@implementation PushTransition
// This is used for percent driven interactive transitions, as well as for container controllers that have companion animations that might need to
// synchronize with the main animation.
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext
{
return 1.0f;
}
// This method can only be a nop if the transition is interactive and not a percentDriven interactive transition.
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
self.transitionContext = transitionContext;
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
//不添加的話辜窑,屏幕什么都沒(méi)有
UIView *containerView = [transitionContext containerView];
[containerView addSubview:fromVC.view];
[containerView addSubview:toVC.view];
CGRect originRect = CGRectMake(0, 0, 50, 50);
UIBezierPath *maskStartPath = [UIBezierPath bezierPathWithOvalInRect:originRect];
UIBezierPath *maskEndPath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(originRect, -2000, -2000)];
//創(chuàng)建一個(gè)CAShapeLayer來(lái)負(fù)責(zé)展示圓形遮蓋
CAShapeLayer *maskLayer = [CAShapeLayer layer];
// maskLayer.path = maskEndPath.CGPath;//將他的path指定為最終的path钩述,來(lái)避免在動(dòng)畫(huà)完成后回彈
toVC.view.layer.mask = maskLayer;
CABasicAnimation *maskAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
maskAnimation.fromValue = (id)maskStartPath.CGPath;
maskAnimation.toValue = (id)maskEndPath.CGPath;
maskAnimation.duration = [self transitionDuration:transitionContext];
maskAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
maskAnimation.fillMode = kCAFillModeForwards;
maskAnimation.removedOnCompletion = NO;
maskAnimation.delegate = self;
[maskLayer addAnimation:maskAnimation forKey:@"Path"];
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
NSLog(@"搞定結(jié)束");
[self.transitionContext completeTransition:![self.transitionContext transitionWasCancelled]];
//去除mask
[self.transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view.layer.mask = nil;
[self.transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view.layer.mask = nil;
}
@end
實(shí)例程序二
實(shí)現(xiàn)從下方彈出的效果
NSTimeInterval duration = [self transitionDuration:transitionContext];
CGRect screenBounds = [[UIScreen mainScreen]bounds];
CGRect finalFrame = [transitionContext finalFrameForViewController:toVC];
toVC.view.frame = CGRectOffset(finalFrame, 0, screenBounds.size.height);
[UIView animateWithDuration:duration delay:0.0 usingSpringWithDamping:0.6 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
toVC.view.frame = finalFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];