1、TransitionFromViewController
这种方法适合在childViewController之间切换
//翻页效果
// UIViewAnimationOptionTransitionCurlUp,
// UIViewAnimationOptionTransitionCurlDown
// 翻转效果
// UIViewAnimationOptionTransitionFlipFromLeft,
// UIViewAnimationOptionTransitionFlipFromRight
// UIViewAnimationOptionTransitionFlipFromTop,
UIViewAnimationOptionTransitionFlipFromDown
[self transitionFromViewController : self.childControllers[1]
toViewController : self.childControllers[2]
duration : 0.5
options : UIViewAnimationOptionTransitionFlipFromRight
animations : ^{
}
completion : ^(BOOL finished){
}];
2、Transition Animation
自定义转场动画一般需要两个对象
- UIViewControllerTransitioningDelegate
(指定UIViewControllerAnimatedTransitioning对象) - UIViewControllerAnimatedTransitioning(实现转场动画的所有细节)
FirstVC
- (void)goAction:(UIButton*)sender{
SecondViewController *secondVC = [[SecondViewController alloc]init];
secondVC.transitioningDelegate = self;
secondVC.modalPresentationStyle = UIModalPresentationCustom;
[self presentViewController:secondVC animated:YES completion:nil];
}
#pragma mark - UIViewControllerTransitionDelegate
- (id)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
AnimatorTransition *animatorTransition = [[AnimatorTransition alloc]init];
// animatorTransition.animatorTransitionType = kAnimatorTransitionTypePresent;
animatorTransition.animatorTransitionType = kAnimatorTransitionTypeBubble;
animatorTransition.bubbleCenter = self.btn.center;
return animatorTransition;
}
- (id)animationControllerForDismissedController:(UIViewController *)dismissed{
AnimatorTransition *animatorTransition = [[AnimatorTransition alloc]init];
// animatorTransition.animatorTransitionType = kAnimatorTransitionTypeDismiss;
animatorTransition.animatorTransitionType = kAnimatorTransitionTypeBubbleBack;
animatorTransition.bubbleCenter = self.btn.center;
return animatorTransition;
}
AnimatorTransition
#import
#import
typedef NS_ENUM(NSInteger,AnimatorTransitionType) {
kAnimatorTransitionTypePresent = 0,
kAnimatorTransitionTypeDismiss,
kAnimatorTransitionTypeBubble,
kAnimatorTransitionTypeBubbleBack
};
@interface AnimatorTransition : NSObject
//转场动画上下文
@property (nonatomic, weak) id transitionContext;
//转场动画过程中呈现出来的View
@property (nonatomic,retain) UIView *containerView;
//转场动画类型
@property (nonatomic,assign)AnimatorTransitionType animatorTransitionType;
@property (nonatomic,retain) UIViewController *from;
@property (nonatomic,retain) UIViewController *to;
@property (nonatomic,retain) UIView *fromView;
@property (nonatomic,retain) UIView *toView;
@property (nonatomic,assign) CGPoint bubbleCenter;
@end
@implementation AnimatorTransition
/**
* 转场动画所需要的时间
*/
- (NSTimeInterval)transitionDuration:(id)transitionContext{
return 1.0;
}
/**
* 转场动画完成调用的方法
*/
- (void)animationEnded:(BOOL)transitionCompleted{
}
/**
* 转场动画细节实现
*/
- (void)animateTransition:(id)transitionContext{
//得到转场过程中的View
_transitionContext = transitionContext;
_containerView = [transitionContext containerView];
_containerView.backgroundColor = [UIColor whiteColor];
//得到转场的两上VC
_from = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
_to = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// 得到
// iOS8之后才有
if ([transitionContext respondsToSelector:@selector(viewForKey:)]) {
_fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
_toView = [transitionContext viewForKey:UITransitionContextToViewKey];
} else {
_fromView = _from.view;
_toView = _to.view;
}
if (self.animatorTransitionType == kAnimatorTransitionTypePresent) {
[self animatorPresent];
}
if (self.animatorTransitionType == kAnimatorTransitionTypeDismiss) {
[self animatorDismiss];
}
if (self.animatorTransitionType == kAnimatorTransitionTypeBubble){
[self animatorBubble];
}
if (self.animatorTransitionType == kAnimatorTransitionTypeBubbleBack) {
[self animatorBubbleBack];
}
}
下面是两种动画的实现过程,大致原理都相近,相比而言spring动画在效果上可能会更好一点。另外如果项目中有多种复杂的自定义页面的话最好就建基类进行继承
#pramgarm mark - bubble动画
- (void)animatorBubble{
// 在toView的下边, 添加了一个bubbleView, 从最初的bubble的center位置开始, 通过scale动画呈现出来.
// BubbleView与toView的背景色一致.
UIView *bubbleView = [[UIView alloc] init];
bubbleView.backgroundColor = self.toView.backgroundColor;
CGSize toViewSize = self.toView.frame.size;
CGFloat x = fmax(_bubbleCenter.x, toViewSize.width);
CGFloat y = fmax(_bubbleCenter.y, toViewSize.height);
CGFloat radius = sqrt(x * x + y * y);
bubbleView.frame = CGRectMake(0, 0, radius * 2, radius * 2);
bubbleView.layer.cornerRadius = CGRectGetHeight(bubbleView.frame) / 2;
bubbleView.transform = CGAffineTransformMakeScale(0.001, 0.001);
bubbleView.center = _bubbleCenter;
[self.containerView addSubview:bubbleView];
// toView要跟随bubbleView一起做动画
self.toView.frame = [self.transitionContext finalFrameForViewController:self.to];
self.toView.transform = CGAffineTransformMakeScale(0.001, 0.001);
self.toView.center = _bubbleCenter;
self.toView.alpha = 0.0;
[self.containerView addSubview:self.toView];
[UIView animateWithDuration:[self transitionDuration:self.transitionContext]
animations:^{
bubbleView.transform = CGAffineTransformIdentity;
self.toView.transform = CGAffineTransformIdentity;
self.toView.alpha = 1.0f;
} completion:^(BOOL finished) {
[self.transitionContext completeTransition:![self.transitionContext transitionWasCancelled]];
}];
}
- (void)animatorBubbleBack{
self.toView.frame = [self.transitionContext finalFrameForViewController:self.to];
[self.containerView insertSubview:self.toView belowSubview:self.fromView];
// 与present bubble时的过程相反.
UIView *bubbleView = [[UIView alloc] init];
bubbleView.backgroundColor = self.fromView.backgroundColor;
CGSize fromViewSize = self.fromView.frame.size;
CGFloat x = fmax(_bubbleCenter.x, fromViewSize.width);
CGFloat y = fmax(_bubbleCenter.y, fromViewSize.height);
CGFloat radius = sqrt(x * x + y * y);
bubbleView.frame = CGRectMake(0, 0, radius * 2, radius * 2);
bubbleView.layer.cornerRadius = radius;
bubbleView.layer.masksToBounds = YES;
// bubbleView.transform = CGAffineTransformIdentity;
bubbleView.center = _bubbleCenter;
[self.containerView insertSubview:bubbleView belowSubview:self.fromView];
[UIView animateWithDuration:[self transitionDuration:self.transitionContext]
animations:^{
bubbleView.transform = CGAffineTransformMakeScale(0.001, 0.001);
self.fromView.transform = CGAffineTransformMakeScale(0.001, 0.001);
self.fromView.center = self.bubbleCenter;
} completion:^(BOOL finished) {
[self.transitionContext completeTransition:![self.transitionContext transitionWasCancelled]];
}];
}
#pragma mark - 简单的呈现动画
- (void)animatorPresent{
//得到初始frame,fromView为全屏,toView为(0,0,0,0)
self.fromView.frame = [self.transitionContext initialFrameForViewController:self.from];
self.toView.frame = [self.transitionContext initialFrameForViewController:self.to];
[self.containerView addSubview:self.toView];
//从中间扩散
self.toView.alpha = 0;
self.toView.center = self.containerView.center;
self.toView.transform = CGAffineTransformMakeScale(0.001, 0.001);
[UIView animateWithDuration:[self transitionDuration:self.transitionContext]
delay:0
usingSpringWithDamping:100// 弹簧效果,越小越明显
initialSpringVelocity:3 //初始速度
options:UIViewAnimationOptionCurveLinear
animations:^{
self.toView.transform = CGAffineTransformIdentity;
self.toView.frame = [self.transitionContext finalFrameForViewController:self.to];
self.toView.alpha = 1;
} completion:^(BOOL finished) {
//这个方法代表告诉系统转都转场成功了
BOOL wasCancelled = [self.transitionContext transitionWasCancelled];
[self.transitionContext completeTransition:!wasCancelled];
}];
}
- (void)animatorDismiss{
/**
* 返回时toView,fromView的frame都是全屏
*/
[self.containerView addSubview:self.fromView];
//[self.containerView insertSubview:self.toView belowSubview:self.fromView];
[UIView animateWithDuration:[self transitionDuration:self.transitionContext]
delay:0
usingSpringWithDamping:100// 弹簧效果,越小越明显
initialSpringVelocity:3 //初始速度
options:UIViewAnimationOptionCurveLinear
animations:^{
self.fromView.transform = CGAffineTransformMakeScale(0.001, 0.001);
self.fromView.frame = CGRectZero;
self.fromView.center = self.containerView.center;
}
completion:^(BOOL finished) {
BOOL wasCancelled = [self.transitionContext transitionWasCancelled];
[self.transitionContext completeTransition:!wasCancelled];
[self.fromView removeFromSuperview];
}];
}
类似
- UINavigationControllerDelegate
- UITabBarControllerDelegate
self.navigationController.delegate = self;
[self.navigationController pushViewController:itemVC animated:YES];
代理方法
- (id )navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC;
- (nullable id )navigationController:(UINavigationController *)navigationController
interactionControllerForAnimationController:(id ) animationController ;
- (id )tabBarController:(UITabBarController *)tabBarController
animationControllerForTransitionFromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC;
- (id )tabBarController:(UITabBarController *)tabBarController
interactionControllerForAnimationController:(id )animationController;
PS:
参考文档1提供了具体的Demo,参考文档2有详细的讲解。
时间有限不能深入学习,先就到这儿。
参考文档1
参考文档2