主要分为 自定义视图控制器过渡(时间的函数) 和 交互式视图控制器过渡(手势)。
所有的过渡,都会创建一个
过渡协调器
。将UICollectionViewController集合视图控制器的
useLayoutToLayoutNavigationTransitions
属性设置为YES,在将集合视图推入导航控制器之前,推入过渡会使用 setCollectionViewLayout:animated: 来完成集合视图布局的变化。iOS 7中可以 取消交互式导航控制器过渡,那么要注意可能出现的问题,第一个控制器的ViewWillDisappear,但不会调用ViewDidAppear和ViewDidDisappear。第二个控制器的ViewWillAppear会调用,但ViewDidAppear不会被调用。无论过渡成功或失败都可以通过notifyWhenInteractionChanges收到通知
自定义视图控制器过渡
// 给跳转的控制器的过渡效果设置代理
dest.transitioningDelegate = self;
// 实现 UIViewControllerTransitioningDelegate 协议方法
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
return 1.0f;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
// 获得将要消失或出现的视图控制器的指针,可以设置透明度、frame的改变等实现一些动画效果
UIViewController *src = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *dest = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
}
// 负责返回动画对象
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
return self;
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
return self;
}
交互式过渡动画
不需要实现animateTransition:方法,而是要实现startInteractiveTransition:方法,这个方法里只能有一个动画块。动画应该基于UIView而不是图层,交互式过渡不支持CATransition或CALayer动画。
// 一、在需要实现过渡动画的控制器内实现以下协议方法
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
return 1.0f;
}
// 协议 <UIViewControllerInteractiveTransitioning>
- (void)startInteractiveTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
UIViewController *src = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
CGPoint centerPoint = src.view.center;
[UIView animateWithDuration:1.0 animations:^{
src.view.frame = CGRectMake(centerPoint.x, centerPoint.y, 10, 10);
src.view.center = centerPoint;
} completion:^(BOOL finished) {
// 如果取消了过渡,这里要返回 NO,否则会多出一个遮挡视图 UITransitionView
[transitionContext completeTransition:YES];
}];
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
return self;
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
return self;
}
- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator {
return self.animator; // 继承自 UIPercentDrivenInteractiveTransition
}
- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator {
return self.animator; // UIPercentDrivenInteractiveTransition
}
// 二、初始化过渡交互动画,并将手势与动画绑定
self.animator = [[SCTPercentDrivenAnimator alloc] initWithViewController:self];
UIPinchGestureRecognizer *gr = [[UIPinchGestureRecognizer alloc] initWithTarget:self.animator
action:@selector(pinchGestureAction:)];
[self.view addGestureRecognizer:gr];
// 三、过渡动画类的实现
@interface SCTPercentDrivenAnimator (/*Private Methods*/)
@property (nonatomic, assign) float startScale;
@property (weak, nonatomic) UIViewController *controller;
@end
@implementation SCTPercentDrivenAnimator
-(instancetype) initWithViewController:(UIViewController*) controller {
if((self = [super init])) {
self.controller = controller;
}
return self;
}
-(void) pinchGestureAction:(UIPinchGestureRecognizer*) gestureRecognizer {
CGFloat scale = gestureRecognizer.scale;
if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {
self.startScale = scale;
[self.controller dismissViewControllerAnimated:YES completion:nil];
}
if(gestureRecognizer.state == UIGestureRecognizerStateChanged) {
CGFloat completePercent = 1.0 - (scale/self.startScale);
[self updateInteractiveTransition:completePercent];
}
if(gestureRecognizer.state == UIGestureRecognizerStateEnded) {
if(gestureRecognizer.velocity >= 0)
[self cancelInteractiveTransition];
else
[self finishInteractiveTransition];
}
if(gestureRecognizer.state == UIGestureRecognizerStateCancelled) {
[self cancelInteractiveTransition];
}
}
@end
网友评论