如何实现左滑返回(1)

前言

以前一直在做产品,感觉技术已经大幅度落后时代了,这是实话,但是最近换了工作,比较闲一点了可以有自己的时间去实现一点自己感兴趣的东西。

正文

好吧,其实这一块的知识点可以追溯到2013年,IOS7刚刚推出来,只怪那时候也刚换工作,而且日复一日的重复体力劳动,完全失去了学习的方向。
闲话不多说,我们知道Push  Pop 以及Present可以实现基本的页面跳转,但是由于IOS更多的工程师加入,我们也不再满足这简单的动画跳转,于是页面跳转的方式也变的多样化,我会从简单的ViewControl跳转讲起,然后再去探索哪个抽屉控件的实现,其实知识点是由一定的关联性的,不得不佩服,苹果在IOS7的时候对ViewControl做出的惊人改革。

我们可能了解,如果要实现页面跳转实现一些动画该怎么实现。没错
[self addChildViewController:toVC];
[fromVC willMoveToParentViewController:nil];
[self.view addSubview:toVC.view];

__weak id weakSelf = self;  
[self transitionFromViewController:fromVC
                  toViewController:toVC duration:0.3
                           options:UIViewAnimationOptionTransitionCrossDissolve
                        animations:^{}
                        completion:^(BOOL finished) {
    [fromVC.view removeFromSuperView];
    [fromVC removeFromParentViewController];
    [toVC didMoveToParentViewController:weakSelf];
}];

我们可以使用一些系统提供的封装过的,或者自己实现,但是这样做无疑是高耦合度的,所以苹果引入了一套新的东西,就是需要解耦开两个页面的跳转问题。

IOS7新增的API:

@protocol UIViewControllerTransitioningDelegate <NSObject>

我希望大家只要理解这个就可以,因为下面的一些协议或者方法,其实都是服务于这个产生的,他负责了页面跳转的对方开发,看看里面方法吧,非常简单:
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator;

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator;

- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source NS_AVAILABLE_IOS(8_0);

当然最下面是IOS8新加的我们暂时不看,看前面4个就知道了啊,1,3负责POP ,2,4后面两个负责Dismiss,那么好,我们先看Pop,也就是1,3,看他们的返回

@protocol UIViewControllerInteractiveTransitioning <NSObject>
- (void)startInteractiveTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

@optional
- (CGFloat)completionSpeed;
- (UIViewAnimationCurve)completionCurve;

@end

@protocol UIViewControllerAnimatedTransitioning <NSObject>

// 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:(id <UIViewControllerContextTransitioning>)transitionContext;
// This method can only  be a nop if the transition is interactive and not a percentDriven interactive transition.
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;


@optional

// This is a convenience and if implemented will be invoked by the system when the transition context's completeTransition: method is invoked.
- (void)animationEnded:(BOOL) transitionCompleted;

@end

返回的就是这两个协议
他们一个负责交互,一个负责交互的动画,如果简单的讲,我们只要实现交互动画,就能替换掉那些系统的low的动画了,那么交互协议呢?有什么用,我们看到里面也十分简单,其实不然,他的作用还是主要服务于手势动画,我们后面会讲。

那就变的很简单了,我们只要实现这些交互动画,就能实现自定义的页面跳转了,so easy!!


为了封装性,我们将动画封装成一个类:PushAnimation

他需要继承的协议就是
UIViewControllerAnimatedTransitioning
然后实现的两个协议方法:

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 10.8f;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    // 1. Get controllers from transition context
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    // 2. Set init frame for toVC
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    CGRect finalFrame = [transitionContext finalFrameForViewController:toVC];
    toVC.view.frame = CGRectOffset(finalFrame, 0, - screenBounds.size.height);
    
    // 3. Add toVC's view to containerView
    UIView *containerView = [transitionContext containerView];
    [containerView addSubview:toVC.view];
    
    // 4. Do animate now
    NSTimeInterval duration = [self transitionDuration:transitionContext];
    [UIView animateWithDuration:duration
                          delay:0.0
         usingSpringWithDamping:0.6
          initialSpringVelocity:0.0
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                         toVC.view.frame = finalFrame;
                     } completion:^(BOOL finished) {
                         // 5. Tell context that we completed.
                         [transitionContext completeTransition:YES];
                     }];
}

OK拉,这时候引出来了另一个东西
@protocol UIViewControllerContextTransitioning


这个是神马鬼!,看名字了交互的上下文,也就是我们能够从上下文中拿到我们需要的一些东西咯,看API
- (CGRect)initialFrameForViewController:(UIViewController *)vc;
- (CGRect)finalFrameForViewController:(UIViewController *)vc;
- (UIViewController *)viewControllerForKey:(NSString *)key;
- (UIView *)viewForKey:(NSString *)key;
- (UIView *)containerView;

里面的API众多,但是我只挑选了比较实用的几条,前面的两条其实从方法名就十分清楚,可以得到ViewController的初始化和最终展现的Frame,至于是FromViewController还是ToViewController,我们可以通过第三条API取到,Key目前就开放了两个
UIKIT_EXTERN NSString *const UITransitionContextFromViewControllerKey NS_AVAILABLE_IOS(7_0);
UIKIT_EXTERN NSString *const UITransitionContextToViewControllerKey NS_AVAILABLE_IOS(7_0);

至于以后会不会增加不得而知了,相信两个Key表达的意思再清楚不过了吧。

这样我们就拿到了一些我们需要实现交互动画的信息了,比如frame,比如位置啊神马的。

看吧是不是很简单,这样我们就实现了最简单的一个自动义转场动画了,然后再需要用的地方

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(50, 50, 100, 30);
    button.backgroundColor = [UIColor redColor];
    [button setTitle:@"push" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(pushNext) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)pushNext
{
    NextViewController * next = [[NextViewController alloc] init];
    next.transitioningDelegate = self;
    [self presentViewController:next animated:YES completion:NULL];
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
{
    return [PushAnimation new];
}

简单吧!

那么另外的一个协议就是我们刚刚讲到的 UIViewControllerInteractiveTransitioning

他的作用就是手势转场了。


我们在下一篇再讲咯!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值