iOS技术iOS学习iOS 开发每天分享优质文章

自定义Modal转场-模仿push & pop

2016-09-01  本文已影响268人  gitKong

前言:

1.gif

自定义转场需要用到什么东西?

一步一个脚印,代码实现来了,具体分析代码中有注释~

.h文件:
* * * * * * * * * * * * * * * * * * * * * * * *
#import <Foundation/Foundation.h>

// present or dismiss
typedef enum{
    FLTransitionAnimationTypePresent,
    FLTransitionAnimationTypeDismiss
}FLTransitionAnimationType;

// present direction
typedef enum{
    FLPresentDirectionTypeFromLeft,
    FLPresentDirectionTypeFromRight
}FLPresentDirectionType;

// present direction
typedef enum{
    FLDismissDirectionTypeFromLeft,
    FLDismissDirectionTypeFromRight
}FLDismissDirectionType;

@interface FLTransitionAnimation : NSObject

/**
 *  @author 孔凡列, 16-09-02 02:09:13
 *
 *  present or dismiss
 */
@property (nonatomic,assign)FLTransitionAnimationType fl_transitionAnimationType;
/**
 *  @author 孔凡列, 16-09-02 04:09:56
 *
 *  present direction
 */
@property (nonatomic,assign)FLPresentDirectionType fl_presentDirectionType;
/**
 *  @author 孔凡列, 16-09-02 04:09:05
 *
 *  dismiss direction
 */
@property (nonatomic,assign)FLDismissDirectionType fl_dismissDirectionType;

@end
.m文件:
* * * * * * * * * * * * * * * * * * * * * * * *
#import "FLTransitionAnimation.h"
@import UIKit;

@interface FLTransitionAnimation () <UIViewControllerAnimatedTransitioning>

@end

@implementation FLTransitionAnimation
// 动画执行的时间
static const CGFloat duration = 0.3;
/**
 *  @author 孔凡列, 16-09-02 04:09:30
 *
 *  返回动画执行的时间
 *
 *  @param transitionContext 实现动画效果时可以从参数transitionContext中获取到切换时的上下文信息,比方说从哪个VC切换到哪个VC等
 *
 *  @return return value description
 */
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return duration;
}

/**
 *  @author 孔凡列, 16-09-02 04:09:25
 *
 *  执行具体动画
 *
 *  @param transitionContext 上下文信息
 */
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    
    if (self.fl_transitionAnimationType == FLTransitionAnimationTypePresent) {
        // 1.get toView
        UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
        // 2.change frame
        __block CGRect tempFrame = toView.frame;
        if (self.fl_presentDirectionType == FLPresentDirectionTypeFromRight) {
            tempFrame.origin.x = toView.frame.size.width;
        }
        else if (self.fl_presentDirectionType == FLPresentDirectionTypeFromLeft) {
            tempFrame.origin.x = -toView.frame.size.width;
        }
        toView.frame = tempFrame;
        // 3.begin animation
        [UIView animateWithDuration:duration animations:^{
            tempFrame.origin.x = 0;
            toView.frame = tempFrame;
        } completion:^(BOOL finished) {
            // 4.Tell context that we completed
            [transitionContext completeTransition:YES];
        }];
    }
    else if (self.fl_transitionAnimationType == FLTransitionAnimationTypeDismiss){
        // 1.get toView
        UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
        // 2.change frame
        __block CGRect tempFrame = fromView.frame;
        // 3.begin animation
        [UIView animateWithDuration:duration animations:^{
            if (self.fl_dismissDirectionType == FLDismissDirectionTypeFromRight) {
                tempFrame.origin.x = -fromView.frame.size.width;
            }
            else if (self.fl_dismissDirectionType == FLDismissDirectionTypeFromLeft) {
                tempFrame.origin.x = fromView.frame.size.width;
            }
            fromView.frame = tempFrame;
        } completion:^(BOOL finished) {
            // 4.Tell context that we completed
            [transitionContext completeTransition:YES];
        }];
    }
}

@end
.h 文件
* * * * * * * * * * * * * * * * * * * * * * * *
#import <Foundation/Foundation.h>
@import UIKit;
// present direction
typedef enum{
    FLPresentTypeFromLeft,
    FLPresentTypeFromRight
}FLPresentType;

// present direction
typedef enum{
    FLDismissTypeFromLeft,
    FLDismissTypeFromRight
}FLDismissType;

@interface FLTransitionManager : NSObject<UIViewControllerTransitioningDelegate>

/**
 *  @author 孔凡列, 16-09-02 04:09:56
 *
 *  present direction
 */
@property (nonatomic,assign)FLPresentType fl_presentType;
/**
 *  @author 孔凡列, 16-09-02 04:09:05
 *
 *  dismiss direction
 */
@property (nonatomic,assign)FLDismissType fl_dismissType;

// 创建一个单例实例

+ (instancetype)shareManager;

@end
.m 文件
* * * * * * * * * * * * * * * * * * * * * * * *
#import "FLTransitionManager.h"
// 具体动画实例
#import "FLTransitionAnimation.h"

@interface FLTransitionManager ()

@end

@implementation FLTransitionManager

static FLTransitionManager *_instance = nil;
+ (instancetype)shareManager{
    if (!_instance) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[self alloc] init];
            // 设置默认值
            _instance.fl_presentType = FLPresentTypeFromRight;
            _instance.fl_dismissType = FLDismissTypeFromLeft;
        });
    }
    return _instance;
}

/**
 *  @author 孔凡列, 16-09-02 05:09:10
 *
 *  present 调用
 *
 *  @param presented  被 present 的控制器
 *  @param presenting 正在 present 的控制器
 *  @param source     The view controller whose presentViewController:animated:completion: method was called. 就是调present那个控制器
 *
 *  @return 返回一个动画实例
 */
- (id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
    FLTransitionAnimation *presentA = [[FLTransitionAnimation alloc] init];
    presentA.fl_transitionAnimationType = FLTransitionAnimationTypePresent;
    if (self.fl_presentType == FLPresentTypeFromLeft) {
        presentA.fl_presentDirectionType = FLPresentDirectionTypeFromLeft;
    }
    else{
        presentA.fl_presentDirectionType = FLPresentDirectionTypeFromRight;
    }
    return presentA;
}

/**
 *  @author 孔凡列, 16-09-02 05:09:20
 *
 *  dismiss 调用
 *
 *  @param dismissed 要dismiss的控制器
 *
 *  @return 返回一个动画实例
 */
- (id )animationControllerForDismissedController:(UIViewController *)dismissed{
    FLTransitionAnimation *dismissA = [[FLTransitionAnimation alloc] init];
    dismissA.fl_transitionAnimationType = FLTransitionAnimationTypeDismiss;
    if (self.fl_dismissType == FLDismissTypeFromLeft) {
        dismissA.fl_dismissDirectionType = FLDismissDirectionTypeFromLeft;
    }
    else if (self.fl_dismissType == FLDismissTypeFromRight){
        dismissA.fl_dismissDirectionType = FLDismissDirectionTypeFromRight;
    }
    return dismissA;
}
@end
.h 文件
* * * * * * * * * * * * * * * * * * * * * * * *
#import <UIKit/UIKit.h>

@interface FLPresentationController : UIPresentationController

@end

* * * * * * * * * * * * * * * * * * * * * * * *
.m文件

#import "FLPresentationController.h"

@implementation FLPresentationController{
    // cover view
    UIView *coverView;
}
/**
 *  @author 孔凡列, 16-09-02 06:09:59
 *
 *  重写构造方法,添加效果
 *
 *  @param presentedViewController  被present 的控制器
 *  @param presentingViewController 正在present 的控制器
 *
 *  @return return value description
 */
- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController{
    if (self = [super initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController]) {
        // 添加一些特效什么的~~~这里简单添加了一个遮盖的view,简单做效果演示
        coverView = [[UIView alloc] init];
        coverView.backgroundColor = [UIColor redColor];
        coverView.alpha = 0.0;
    }
    return self;
}

/**
 *  @author 孔凡列, 16-09-02 05:09:36
 *
 *  准备present
 */
- (void)presentationTransitionWillBegin{
    NSLog(@"present will begin");
   // 简单添加效果
    coverView.frame = self.containerView.bounds;
    [self.containerView addSubview:coverView];
    
    // 最重要的 最重要的 最重要的 添加要present的view到容器里面,不然无法present,因为系统都不知道present什么,而且一定要最后添加
    [self.containerView addSubview:self.presentedView];
    
    id<UIViewControllerTransitionCoordinator> coordinator = self.presentingViewController.transitionCoordinator;
    
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        coverView.alpha = 1;
    } completion:nil];
}
/**
 *  @author 孔凡列, 16-09-02 06:09:12
 *
 *  present 结束
 *
 *  @param completed completed description
 */
- (void)presentationTransitionDidEnd:(BOOL)completed{
    NSLog(@"present did end");
    if(!completed){
        [coverView removeFromSuperview];
    }
}
/**
 *  @author 孔凡列, 16-09-02 06:09:15
 *
 *  准备 dismiss
 */
- (void)dismissalTransitionWillBegin{
    
    NSLog(@"dismiss will begin");
    id<UIViewControllerTransitionCoordinator> coordinator = self.presentingViewController.transitionCoordinator;
    
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        coverView.alpha = 0.0;
    } completion:nil];
}
/**
 *  @author 孔凡列, 16-09-02 06:09:18
 *
 *  dismiss 结束
 *
 *  @param completed completed description
 */
- (void)dismissalTransitionDidEnd:(BOOL)completed{
    NSLog(@"dismiss did end");
    if(completed){
        [coverView removeFromSuperview];
    }
}
/**
 *  @author 孔凡列, 16-09-02 05:09:19
 *
 *  返回一个 用来控制 controller 之间的跳转特效 的控制器 (注意此API是 iOS8之后才有)
 *
 *  @param presented  被 present 的控制器
 *  @param presenting 正在 present 的控制器
 *  @param source     谁调present
 *
 *  @return 返回一个 用来控制 controller 之间的跳转特效 的控制器
 */
- (nullable UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source NS_AVAILABLE_IOS(8_0){
    return [[FLPresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting];
}
    SecondViewController  *vc = [[SecondViewController alloc] init];
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
    
    nav.modalPresentationStyle = UIModalPresentationCustom;
    nav.transitioningDelegate = [FLTransitionManager shareManager];
    
    [self presentViewController:nav animated:YES completion:nil];


    dismiss 直接调,什么都不用设置
    [self dismissViewControllerAnimated:YES completion:nil];
2.gif

总结来了!

iOS 7中视图控制器切换.png

恩,还不够清楚!参考这个-->iOS7之定制View Controller切换效果

系统的pop 就是交互式切换的,因此,上面的还不算高仿,入栈这个不搞了,往后就先弄个拖拽手势~期待ing

上一篇 下一篇

猜你喜欢

热点阅读