第六十五篇、iOS7自定义转场动画

自定义转场动画,在iOS7及以上的版本才开始出现的,在一些应用中,我们常常需要定制自定义的的跳转动画

1.遵守协议:<UIViewControllerAnimatedTransitioning>

2.协议的方法主要的是两个:

// 指定动画的持续时长 1. (NSTimeInterval)transitionDuration; // 转场动画的具体内容 2. (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

typedef NS_ENUM(NSUInteger, HYBControllerTransitionType) {
  kControllerTransitionPush = 1 << 1,
  kControllerTransitionPop = 1 << 2
};

@interface HYBControllerTransition : NSObject <UIViewControllerAnimatedTransitioning>

+ (instancetype)transitionWithType:(HYBControllerTransitionType)transitionType
                          duration:(NSTimeInterval)duration;

@end
#import "HYBControllerTransition.h"
#import "ViewController.h"
#import "DetailController.h"

@interface HYBControllerTransition ()

@property (nonatomic, assign) HYBControllerTransitionType transitionType;
@property (nonatomic, assign) NSTimeInterval duration;

@end

@implementation HYBControllerTransition

- (instancetype)init {
  if (self = [super init]) {
    self.transitionType = kControllerTransitionPush;
  }

  return self;
}

+ (instancetype)transitionWithType:(HYBControllerTransitionType)transitionType
                          duration:(NSTimeInterval)duration {
  HYBControllerTransition *transition = [[HYBControllerTransition alloc] init];
  transition.transitionType = transitionType;
  transition.duration = duration;

  return transition;
}

#pragma mark - UIViewControllerAnimatedTransitioning
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
  switch (self.transitionType) {
    case kControllerTransitionPush: {
      [self push:transitionContext];
      break;
    }
    case kControllerTransitionPop: {
      [self pop:transitionContext];
      break;
    }
    default: {
      break;
    }
  }
}

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
  return self.duration;
}

- (void)animationEnded:(BOOL)transitionCompleted {
  NSLog(@"%s", __FUNCTION__);
}

#pragma mark - Private
- (void)pop:(id<UIViewControllerContextTransitioning>)transitionContext {
  DetailController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
  ViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
  UIView *containerView = [transitionContext containerView];

  UIView *toImageView = toVC.isImg1 ? toVC.img1 : toVC.img2;

  UIView *tempView = containerView.subviews.lastObject;

  // 第一个view是fromVC.view
  // 第二个view是push进来时所生成的toImageView截图
  for (UIView *view in containerView.subviews) {
    NSLog(@"%@", view);
    if (fromVC.view == view) {
      NSLog(@"YES");
    }
  }

  toImageView.hidden = YES;
  tempView.hidden = NO;
  // 必须保证将toVC.view放在最上面,也就是第一个位置
  [containerView insertSubview:toVC.view atIndex:0];

  [UIView animateWithDuration:self.duration
                        delay:0.0
       usingSpringWithDamping:0.55
        initialSpringVelocity:1/ 0.55
                      options:0
                   animations:^{
                     fromVC.view.alpha = 0.0;
                     tempView.frame = [toImageView convertRect:toImageView.bounds toView:containerView];
  } completion:^(BOOL finished) {
    tempView.hidden = NO;
    toImageView.hidden = NO;
    [tempView removeFromSuperview];

    [transitionContext completeTransition:YES];

    for (UIView *view in containerView.subviews) {
      NSLog(@"%@", view);
      if (toVC.view == view) {
        NSLog(@"YES");
      }
    }
  }];
}

- (void)push:(id<UIViewControllerContextTransitioning>)transitionContext {
  ViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
  DetailController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
  UIView *containerView = [transitionContext containerView];

  UIView *fromImageView = fromVC.isImg1 ? fromVC.img1 : fromVC.img2;
  UIView *tempView = [fromImageView snapshotViewAfterScreenUpdates:NO];
  tempView.frame = [fromImageView convertRect:fromImageView.bounds toView:containerView];

  UIView *toImageView = toVC.imgView;

  fromImageView.hidden = YES;
  toVC.view.alpha = 0.0;
  toImageView.hidden = YES;

  [containerView addSubview:toVC.view];
  [containerView addSubview:tempView];

  [UIView animateWithDuration:self.duration
                        delay:0.0
       usingSpringWithDamping:0.55
        initialSpringVelocity:1/ 0.55
                      options:0
                   animations:^{
                     toVC.view.alpha = 1.0;
                     tempView.frame = [toImageView convertRect:toImageView.bounds toView:containerView];
                   } completion:^(BOOL finished) {
                     tempView.hidden = YES;
                     toImageView.hidden = NO;

                     [transitionContext completeTransition:YES];
                   }];
}
@end

使用遵守Nav协议的方法:

#pragma mark - UINavigationControllerDelegate
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {
  return nil;
}

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
  if (operation == UINavigationControllerOperationPush) {
    return [HYBControllerTransition transitionWithType:kControllerTransitionPush duration:0.75];
  } else {
    return [HYBControllerTransition transitionWithType:kControllerTransitionPop duration:0.75];
  }
}
时间: 2024-08-05 13:16:14

第六十五篇、iOS7自定义转场动画的相关文章

十五篇、自定义线程池之简单的线程池

1 二. #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 import threading 4 import queue 5 import time 6 7 class ThreadPool(object): 8 def __init__(self,max_num = 20): 9 self.queue = queue.Queue(max_num) #创建一个最大长度为20的队列 10 for i in range(max_num): #往队列里面

Python之路【第十五篇】:Web框架

Python之路[第十五篇]:Web框架 Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #!/usr/bin/env python #coding:utf-8   import socket   def handle_request(client):     buf = client.recv(10

QT开发(六十五)——QT样式表编程实例

QT开发(六十五)--QT样式表编程实例 一.QComboBox组合框样式定制 1.基本定义 QComboBox  {     border: 1px solid gray;     border-radius: 3px;     padding: 1px 2px 1px 2px;  # 针对于组合框中的文本内容     min-width: 9em;   # 组合框的最小宽度 } QComboBox::drop-down {     subcontrol-origin: padding;   

Egret入门学习日记 --- 第二十五篇(书中 9.16~9.17 节 内容)

第二十五篇(书中 9.16~9.17 节 内容) 对于昨天的关于 List 组件使用的问题,我打算到书中提到List之后,再回头补充. 还有就是 Scroller 的 TileLayout 布局方式,也要去研究一下. 好了,开始按照书中内容一步一步走. 开始 9.16节. 重点: 1.设定TabBar皮肤. 2.设置TabBar布局. 操作: 1.设定TabBar皮肤. 第一步,准备素材! 第二步,创建 exml 文件! 第三步,拖入组件!约束大小! 第四步,增加两个状态 down 和 up.

秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题 在<秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量>中对经典多线程同步互斥问题进行了回顾和总结,这篇文章对Windows系统下常用的线程同步互斥机制——关键段.事件.互斥量.信号量进行了总结.有网友问到互斥量能处理“遗弃”问题,事件和信号量是否也能处理“遗弃”问题.因此本文将对事件和信号量作个试验,看看事件和信号量能否处理“遗弃”问题. 一.

第十五篇 Integration Services:SSIS参数

本篇文章是Integration Services系列的第十五篇,详细内容请参考原文. 简介在前一篇,我们使用SSDT-BI将第一个SSIS项目My_First_SSIS_Project升级/转换到SSIS 2012.在这一篇,我们将探讨SSIS变量的姊妹:SSIS参数.我们将展示参数配置,通过包参数管理动态属性值,以及在SSIS包执行期间参数是如何配置和使用的.首先在SSDT-BI打开转换过的My_First_SSIS_Project,如图15.1所示:图15.1My_First_SSIS_P

第三百六十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的查询

第三百六十五节,Python分布式爬虫打造搜索引擎Scrapy精讲-elasticsearch(搜索引擎)的查询 elasticsearch(搜索引擎)的查询 elasticsearch是功能非常强大的搜索引擎,使用它的目的就是为了快速的查询到需要的数据 查询分类: 基本查询:使用elasticsearch内置的查询条件进行查询 组合查询:把多个查询条件组合在一起进行复合查询 过滤:查询同时,通过filter条件在不影响打分的情况下筛选数据

第十五篇 和谐

第十五篇  和谐 "和谐"对于整个宇宙来讲至关重要,无论是宇宙自身空间的环境还是万物之间都需要和谐.如果在任何方面或任何领域出现不和谐的因素,就会对宇宙本身及宇宙中的万物带来很大的影响.这种影响大可以使宇宙规律出现混乱,小也会造成宇宙空间中的万物出现变异. 以上讲的这些是针对整个大宇宙背景所作出的描述.从这些真相当中我们可以知道人类世界同样也需要和谐.因为不和谐,我们就无法向上发展.如今人类世界就有很多的空间出现不和谐的因素,这些不和谐的因素一直障碍着整个人类世界的发展.这样的状况,只

NHibernate 过滤器(第十五篇)

NHibernate 过滤器(第十五篇) NHibernate过滤器相当于定义一个非常类似于类和集合上使用的where子句.ISession 中默认是不启用过滤器的,必须通过ISession.EnableFilter()方法显式的启用. 该方法返回被启用的IFilter的实例.这也支持链式操作. 过滤器主要的配置都在映射文件内完成.来看示例: <?xml version="1.0" encoding="utf-8" ?> <hibernate-ma