ios7 push动画封装(pop手势交互)

ios7以上苹果添加了一些新的push动画实现方式,下面是我对一些动画的封装(部分代码参照iOS_7_by_Tutorials_1_1这本书):

废话不多说,还是代码为上。

#import <Foundation/Foundation.h>


typedef enum : NSUInteger {

    AnimatedTransitioningNone,

    AnimatedTransitioningPop,

    AnimatedTransitioningFlip,

    AnimatedTransitioningShrink,

    AnimatedTransitioningBounce,

    AnimatedTransitioningContingent

} AnimatedTransitioningType;


typedef enum : NSUInteger {

    InteractiveTransitioningNone,

    InteractiveTransitioningSwipe

} InteractiveTransitioningType;



@class UserInteractionController;

@interface DHFModel_ControllerAnimation : NSObject


+ (id<UIViewControllerAnimatedTransitioning>)createAnimatedTransitioningWithType:(AnimatedTransitioningType)type;

+ (UserInteractionController *)createInteractiveTransitioningWithType:(InteractiveTransitioningType)type;


@end


#pragma mark - 用户交互操作

/**

 *  @author weloy, 15-11-28 09:11:21

 *

 *  @brief  toViewController添加pan手势

 *

 *  @param viewController <#viewController description#>

 */

@interface UserInteractionController : UIPercentDrivenInteractiveTransition

- (void)wireToViewController:(UIViewController*)viewController;

@property (nonatomic, assign) BOOL interactionInProgress;

@end


#pragma mark - 动画

/**

 *  @author weloy, 15-11-28 09:11:32

 *

 *  @brief  pop回去的动画

 */

@interface PopAnimationController : NSObject <UIViewControllerAnimatedTransitioning>


@end


/**

 *  @author weloy, 15-11-28 09:11:44

 *

 *  @brief  翻转动画

 */

@interface FlipAnimationController : NSObject <UIViewControllerAnimatedTransitioning>

@property (nonatomic, assign) BOOL reverse;

@end


/**

 *  @author weloy, 15-11-28 09:11:54

 *

 *  @brief  截图动画  不可用于pan手势返回

 */

@interface ShrinkDismissAnimationController : NSObject <UIViewControllerAnimatedTransitioning>

@end


/**

 *  @author weloy, 15-11-28 09:11:22

 *

 *  @brief  弹跳动画

 */

@interface BouncePresentAnimationController : NSObject <UIViewControllerAnimatedTransitioning>

@end


@interface ContingentViewAnimationController : NSObject <UIViewControllerAnimatedTransitioning>


@property (nonatomic, strong) NSArray *fromViews;

@property (nonatomic, strong) NSArray *toViews;


@end


代码量有点多,需要的人可以详细看看,或者直接拿码:

下面是.m文件

#import "DHFModel_ControllerAnimation.h"

#import <QuartzCore/QuartzCore.h>


@implementation DHFModel_ControllerAnimation


+ (id<UIViewControllerAnimatedTransitioning>)createAnimatedTransitioningWithType:(AnimatedTransitioningType)type{

    id<UIViewControllerAnimatedTransitioning> animatedTransitioning = nil;

    switch (type) {

        case AnimatedTransitioningPop:

            animatedTransitioning = [[PopAnimationController alloc]init];

            break;

        case AnimatedTransitioningBounce:

            animatedTransitioning = [[BouncePresentAnimationController alloc] init];

            break;

        case AnimatedTransitioningFlip:

            animatedTransitioning = [[FlipAnimationController alloc] init];

            break;

        case AnimatedTransitioningShrink:

            animatedTransitioning = [[ShrinkDismissAnimationController alloc] init];

            break;

        case AnimatedTransitioningContingent:

            animatedTransitioning = [[ContingentViewAnimationController alloc] init];

            break;

        default:

            break;

    }

    return animatedTransitioning;

}


+ (id<UIViewControllerInteractiveTransitioning>)createInteractiveTransitioningWithType:(InteractiveTransitioningType)type{

    UserInteractionController * interactiveTransitioning = nil;

    switch (type) {

        case InteractiveTransitioningSwipe:

            interactiveTransitioning = [[UserInteractionController alloc] init];

            break;

            

        default:

            break;

    }

    return interactiveTransitioning;

}


@end


@implementation UserInteractionController {

    BOOL _shouldCompleteTransition;//是否要完成

    __weak UIViewController *_viewController;

    CGFloat _totalTranslationX;

    BOOL _firstTimeChange;

}


- (void)wireToViewController:(UIViewController *)viewController {

    _viewController = viewController;

    [self prepareGestureRecognizerInView:viewController.view];

}



- (void)prepareGestureRecognizerInView:(UIView*)view {

    UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];

    [view addGestureRecognizer:gesture];

    _totalTranslationX = 0;

    _firstTimeChange = YES;

}


- (CGFloat)completionSpeed

{

    return 1;

}


- (void)handleGesture:(UIPanGestureRecognizer*)gestureRecognizer {

    UIView * view = gestureRecognizer.view.superview;

    CGPoint translation = [gestureRecognizer translationInView:view];

    _totalTranslationX += translation.x;

    [gestureRecognizer setTranslation:CGPointMake(0, 0) inView:view];

//    NSLog(@"translation == %lf total == %f",translation.x,_totalTranslationX);

    if (_totalTranslationX<0||translation.x<0.6) {

        if (!self.interactionInProgress) {

            [self cancelInteractiveTransition];

            return;

        }

    }

    switch (gestureRecognizer.state) {

        case UIGestureRecognizerStateBegan:

            // 1. Start an interactive transition!

            [self beginTransition];

            break;

        case UIGestureRecognizerStateChanged: {

            if (!self.interactionInProgress&&_firstTimeChange) {//有可能没有begin

                if (_totalTranslationX > 5) {

                    [self beginTransition];

                }

            }

            if (_firstTimeChange) {

//                NSLog(@"\n\n\n");

                _firstTimeChange = NO;

            }

            // 2. compute the current position

            CGFloat fraction = fabs(_totalTranslationX / CGRectGetWidth(view.bounds));

            // 3. should we complete?

            _shouldCompleteTransition = (fraction > 0.2);

//            NSLog(@"change");

            // 4. update the animation controller

            [self updateInteractiveTransition:fraction];

            break;

        }

        case UIGestureRecognizerStateEnded:

           

        case UIGestureRecognizerStateCancelled:

            // 5. finish or cancel

            self.interactionInProgress = NO;

            if (!_shouldCompleteTransition || gestureRecognizer.state == UIGestureRecognizerStateCancelled) {

                [self cancelInteractiveTransition];

            }

            else {

                [self finishInteractiveTransition];

            }

            break;

        default:

            break;

    }

}


- (void)cancelInteractiveTransition{

    [super cancelInteractiveTransition];

//    NSLog(@"cancel");

    _totalTranslationX = 0;

    _firstTimeChange = YES;

}


- (void)finishInteractiveTransition{

    [super finishInteractiveTransition];

//    NSLog(@"end");

    _totalTranslationX = 0;

    _firstTimeChange = YES;

}


- (void)beginTransition{

    self.interactionInProgress = YES;

//    NSLog(@"begin");

    [_viewController.navigationController popViewControllerAnimated:YES];

}


- (void)dealloc{


}


@end



@implementation FlipAnimationController


- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {

    

    // 1. the usual stuff ...

    UIView* containerView = [transitionContext containerView];

    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    UIView *toView = toVC.view;

    UIView *fromView = fromVC.view;

    [containerView addSubview:toVC.view];

    

    // 2. Add a perspective transform

    CATransform3D transform = CATransform3DIdentity;

    transform.m34 = -0.002;

    [containerView.layer setSublayerTransform:transform];

    

    // 3. Give both VCs the same start frame

    CGRect initialFrame = [transitionContext initialFrameForViewController:fromVC];

    fromView.frame = initialFrame;

    toView.frame = initialFrame;

    

    // 4. reverse?

    float factor = self.reverse ? 1.0 : -1.0;

    

    // 5. flip the to VC halfway round - hiding it

    toView.layer.transform = [self yRotation:factor * -M_PI_2];

    

    // 6. Animate

    NSTimeInterval duration = [self transitionDuration:transitionContext];

    [UIView animateKeyframesWithDuration:duration

                                   delay:0.0

                                 options:0

                              animations:^{

                                  [UIView addKeyframeWithRelativeStartTime:0.0

                                                          relativeDuration:0.5

                                                                animations:^{

                                                                    // 7. rotate the from view

                                                                    fromView.layer.transform = [self yRotation:factor * M_PI_2];

                                                                }];

                                  [UIView addKeyframeWithRelativeStartTime:0.5

                                                          relativeDuration:0.5

                                                                animations:^{

                                                                    // 8. rotate the to view

                                                                    toView.layer.transform =  [self yRotation:0.0];

                                                                }];

                              } completion:^(BOOL finished) {

                                  BOOL cancel = [transitionContext transitionWasCancelled];

                                  if (cancel) {

                                      toView.layer.transform =  [self yRotation:0.0];

                                      fromView.layer.transform = [self yRotation:0.0];

                                  }

                                  [transitionContext completeTransition:!cancel];

                              }];

}


- (CATransform3D) yRotation:(CGFloat) angle {

    return  CATransform3DMakeRotation(angle, 0.0, 1.0, 0.0);

}


- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {

    return 0.5f;

}


@end



@implementation ShrinkDismissAnimationController


- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {

    return 1.0;

}


- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {

    // 1. obtain state from the context

    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    CGRect finalFrame = [transitionContext finalFrameForViewController:toViewController];

    

    // 2. obtain the container view

    UIView *containerView = [transitionContext containerView];

    

    // 3. set initial state

    toViewController.view.frame = finalFrame;

    toViewController.view.alpha = 0.5;

    

    // 4. add the view

    [containerView addSubview:toViewController.view];

    [containerView sendSubviewToBack:toViewController.view];

    

    // 1. Determine the intermediate and final frame for the from view

    CGRect screenBounds = [[UIScreen mainScreen] bounds];

    CGRect shrunkenFrame = CGRectInset(fromViewController.view.frame, fromViewController.view.frame.size.width/4, fromViewController.view.frame.size.height/4);

    CGRect fromFinalFrame = CGRectOffset(shrunkenFrame, 0, screenBounds.size.height);

    

    // create a snapshot

    UIView *intermediateView = [fromViewController.view snapshotViewAfterScreenUpdates:NO];

    intermediateView.frame = fromViewController.view.frame;

    [containerView addSubview:intermediateView];

    

    // remove the real view

    [fromViewController.view removeFromSuperview];

    

    NSTimeInterval duration = [self transitionDuration:transitionContext];

    

    // animate with keyframes

    [UIView animateKeyframesWithDuration:duration

                                   delay:0.0

                                 options:UIViewKeyframeAnimationOptionCalculationModeCubic

                              animations:^{

                                  // 2a. keyframe one

                                  [UIView addKeyframeWithRelativeStartTime:0.0

                                                          relativeDuration:0.5

                                                                animations:^{

                                                                    intermediateView.frame = shrunkenFrame;

                                                                    toViewController.view.alpha = 0.5;

                                                                }];

                                  // 2b. keyframe two

                                  [UIView addKeyframeWithRelativeStartTime:0.5

                                                          relativeDuration:0.5

                                                                animations:^{

                                                                    intermediateView.frame = fromFinalFrame;

                                                                    toViewController.view.alpha = 1.0;

                                                                }];

                              }

                              completion:^(BOOL finished) {

                                  // 3. inform the context of completion

                                  [intermediateView removeFromSuperview];

                                  [transitionContext completeTransition:YES];

                              }];

    

}


@end



@implementation BouncePresentAnimationController



- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {

    return 0.5;

}


- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {

    // 1. obtain state from the context

    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    CGRect finalFrame = [transitionContext finalFrameForViewController:toViewController];

    

    // 2. obtain the container view

    UIView *containerView = [transitionContext containerView];

    

    // 3. set initial state

    CGRect screenBounds = [[UIScreen mainScreen] bounds];

    toViewController.view.frame = CGRectOffset(finalFrame, 0, screenBounds.size.height);

    

    // 4. add the view

    [containerView addSubview:toViewController.view];

    

    // 5. animate

    NSTimeInterval duration = [self transitionDuration:transitionContext];

    [UIView animateWithDuration:duration

                          delay:0.0

         usingSpringWithDamping:0.6

          initialSpringVelocity:0.0

                        options:UIViewAnimationOptionCurveLinear

                     animations:^{

                         fromViewController.view.alpha = 0.5;

                         toViewController.view.frame = finalFrame;

                     } completion:^(BOOL finished) {

                         // 6. inform the context of completion

                         BOOL cancel = [transitionContext transitionWasCancelled];

                         fromViewController.view.alpha = 1.0;

                         [transitionContext completeTransition:!cancel];

                     }];

}



@end


@implementation PopAnimationController


- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext

{

    return 0.4;

}


- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext

{

    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    UIView *containerView = [transitionContext containerView];

    [containerView insertSubview:toViewController.view belowSubview:fromViewController.view];

    CGRect finalFrame = [transitionContext finalFrameForViewController:toViewController];


    UIView * bgView = [[UIView alloc] initWithFrame:toViewController.view.frame];

    bgView.backgroundColor = [UIColor blackColor];

    bgView.alpha = 0.5;

    [containerView insertSubview:bgView belowSubview:fromViewController.view];


    

    __block CGRect toRect = toViewController.view.frame;

    __block CGRect fromRect = toRect;

    

    CGFloat originX = toRect.origin.x;

    toRect.origin.x -= toRect.size.width / 3;

    toViewController.view.frame = toRect;


    

    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{

        fromRect.origin.x += fromRect.size.width;

        fromViewController.view.frame = fromRect;

        

        bgView.alpha = 0;

        

        toRect.origin.x = originX;

        toViewController.view.frame = toRect;

    } completion:^(BOOL finished) {

        [bgView removeFromSuperview];

        BOOL cancel = [transitionContext transitionWasCancelled];

        if (cancel) {

            toViewController.view.frame = finalFrame;

        }

        [transitionContext completeTransition:!cancel];

    }];

}


@end


@implementation ContingentViewAnimationController


- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext

{

    return 0.4;

}


- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext

{

    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    UIView *containerView = [transitionContext containerView];

    

    NSAssert([self.fromViews count] == [self.toViews count], @"*** The count of fromviews and toviews must be the same! ***");

    

    NSMutableArray *fromViewSnapshotArray = [[NSMutableArray alloc] init];

    for (UIView *fromView in self.fromViews) {

        UIImageView *fromViewSnapshot = [[UIImageView alloc] initWithImage:[UIView imageWithView:fromView]];

        fromViewSnapshot.frame = [containerView convertRect:fromView.frame fromView:fromViewController.view];

        [fromViewSnapshotArray addObject:fromViewSnapshot];

        fromView.hidden = YES;

    }

    

    for (UIView *toView in self.toViews) {

        toView.hidden = YES;

    }

    

    toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController];

    toViewController.view.alpha = 0;

    [containerView addSubview:toViewController.view];

    

    for (NSUInteger i = [fromViewSnapshotArray count]; i > 0; i--) {

        [containerView addSubview:[fromViewSnapshotArray objectAtIndex:i - 1]];

    }

    

    [containerView layoutIfNeeded];

    [UIView animateWithDuration:[self transitionDuration:transitionContext]

                          delay:0.0

         usingSpringWithDamping:0.8

          initialSpringVelocity:1.0

                        options:UIViewAnimationOptionCurveEaseInOut

                     animations:^{

                         toViewController.view.alpha = 1.0;

                         for (NSUInteger i = 0; i < [self.fromViews count]; i++) {

                             UIView *toView = [self.toViews objectAtIndex:i];

                             UIView *fromViewSnapshot = [fromViewSnapshotArray objectAtIndex:i];

                             CGRect frame = [containerView convertRect:toView.frame fromView:toViewController.view];

                             fromViewSnapshot.frame = frame;

                         }

                     } completion:^(BOOL finished) {

                         for (NSUInteger i = 0; i < [self.fromViews count]; i++) {

                             UIView *toView = [self.toViews objectAtIndex:i];

                             UIView *fromView = [self.fromViews objectAtIndex:i];

                             toView.hidden = NO;

                             fromView.hidden = NO;

                             

                             UIView *fromViewSnapshot = [fromViewSnapshotArray objectAtIndex:i];

                             [fromViewSnapshot removeFromSuperview];

                         }

                         

                         [transitionContext completeTransition:!transitionContext.transitionWasCancelled];

                     }];


}


@end


因为篇幅过长,下一篇将要写使用方法,当然还是一个封装类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值