iOS开发自定义转场动画
1、转场动画
iOS7之后开发者可以自定义界面切换的转场动画,就是在模态弹出(present、dismiss),Navigation的(push、pop),TabBar的系统切换效果之外自定义切换动画!
模态弹出自定义出push、pop效果,可以侧滑:

2、实现步骤
2.1、自定义转场动画
1》创建自定义文件
@interface CustomTransform : NSObject<UIViewControllerAnimatedTransitioning>
2》实现UIViewControllerAnimatedTransitioning方法
//设置转场时间
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
//设置转场效果
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
.m相关类说明:
//表示转场动画上下文
UIViewControllerContextTransitioning
//当前控制器fromVC和目标控制器toVC
//vc1-->present-->vc2: fromVC是vc1,toVC是vc2
//vc2-->dismiss-->vc1: fromVC是vc2,toVC是vc1
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
//对应控制器的view视图
UIView *fromView =[transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *toView =[transitionContext viewForKey:UITransitionContextToViewKey]; //presentingViewController,presentedViewController
vc1-->present-->vc2,vc1.presentedViewController 就是vc2;vc2.presentingViewController 就是vc1。 //更新动画进度
- (void)updateInteractiveTransition:(CGFloat)percentComplete;
//转场结束
- (void)finishInteractiveTransition;
//转场取消
- (void)cancelInteractiveTransition;
自定义文件:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h> typedef NS_ENUM(NSInteger, PresentType){
PresentTypePresent,
PresentTypeDismiss
}; @interface CustomTransform : NSObject<UIViewControllerAnimatedTransitioning> + (instancetype)makeWithTransitionType:(PresentType)type;
- (instancetype)initWithTransitionType:(PresentType)type; @end
.h文件
#import "CustomTransform.h" @interface CustomTransform() @property(nonatomic, assign)PresentType type;
@property(nonatomic, strong)UIView *containerView;
@end @implementation CustomTransform
+ (instancetype)makeWithTransitionType:(PresentType)type
{
return [[self alloc] initWithTransitionType:type];
} - (instancetype)initWithTransitionType:(PresentType)type
{
if (self == [super init]) {
_type = type;
}
return self;
} - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext
{
return .;
} - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
switch (_type) {
case PresentTypePresent:
[self presentTransform:transitionContext];
break;
case PresentTypeDismiss:
[self dismissTransform:transitionContext];
break;
default:
break;
} } - (void)presentTransform:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
self.containerView = [transitionContext containerView]; UIView *fromView =[transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *toView =[transitionContext viewForKey:UITransitionContextToViewKey];
[self.containerView addSubview:toView];
CGRect visibleFrame = [transitionContext initialFrameForViewController:fromVC];
CGRect rightHiddenFrame = CGRectMake( CGRectGetWidth(visibleFrame), ,CGRectGetWidth(visibleFrame),CGRectGetHeight(visibleFrame));
CGRect leftHiddenFrame =CGRectMake(- CGRectGetWidth(visibleFrame), , CGRectGetWidth(visibleFrame), CGRectGetHeight(visibleFrame));
fromView.frame = visibleFrame;
toView.frame = rightHiddenFrame;
fromView.layer.masksToBounds = toView.layer.masksToBounds = YES;
[self.containerView insertSubview:toView atIndex:];
[UIView animateWithDuration:.
animations:^{
fromView.frame = leftHiddenFrame;
toView.frame = visibleFrame;
}
completion:^(BOOL finished) {
if ([transitionContext transitionWasCancelled]) {
[toView removeFromSuperview];
}
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}]; } - (void)dismissTransform:(id<UIViewControllerContextTransitioning>)transitionContext
{ UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
self.containerView = [transitionContext containerView]; UIView *fromView =[transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *toView =[transitionContext viewForKey:UITransitionContextToViewKey];
[self.containerView addSubview:toView];
CGRect visibleFrame = [transitionContext initialFrameForViewController:fromVC];
CGRect rightHiddenFrame = CGRectMake( CGRectGetWidth(visibleFrame), ,CGRectGetWidth(visibleFrame),CGRectGetHeight(visibleFrame));
CGRect leftHiddenFrame =CGRectMake(- CGRectGetWidth(visibleFrame), , CGRectGetWidth(visibleFrame), CGRectGetHeight(visibleFrame));
fromView.frame = visibleFrame;
toView.frame = leftHiddenFrame;
fromView.layer.masksToBounds = toView.layer.masksToBounds = YES;
[UIView animateWithDuration:.
animations:^{
fromView.frame = rightHiddenFrame;
toView.frame = visibleFrame;
}
completion:^(BOOL finished) {
if ([transitionContext transitionWasCancelled]) {
[toView removeFromSuperview];
}
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
} @end
.m文件
2.2、自定义交互手势
1》创建自定义文件
@interface CustonInteractive : UIPercentDrivenInteractiveTransition
因为UIPercentDrivenInteractiveTransition : NSObject <UIViewControllerInteractiveTransitioning>,所以自定义时继承遵循UIViewControllerInteractiveTransitioning协议的UIPercentDrivenInteractiveTransition子类!
2》相关文件:
#import <UIKit/UIKit.h> @interface CustonInteractive : UIPercentDrivenInteractiveTransition @property (nonatomic, assign) BOOL interacting; - (void)wireToViewController:(UIViewController*)viewController; @end
.h
#import "CustonInteractive.h" @interface CustonInteractive()
@property (nonatomic, strong) UIViewController *presentingVC; @end @implementation CustonInteractive
-(void)wireToViewController:(UIViewController *)viewController
{
self.presentingVC = viewController;
[self prepareGestureRecognizerInView:viewController.view];
} - (void)prepareGestureRecognizerInView:(UIView*)view {
UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
[view addGestureRecognizer:gesture];
}
- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer {
CGFloat progress = [gestureRecognizer translationInView:gestureRecognizer.view.superview].x / (self.presentingVC.view.bounds.size.width * 1.0);
progress = MIN(1.0, MAX(0.0, progress));//把这个百分比限制在0~1之间
NSLog(@"===%lf",progress);
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
self.interacting = YES;
[self.presentingVC dismissViewControllerAnimated:YES completion:nil];
}
else if (gestureRecognizer.state == UIGestureRecognizerStateChanged){
if (self.interacting) {
[self updateInteractiveTransition:progress];
}
}else if (gestureRecognizer.state == UIGestureRecognizerStateCancelled||gestureRecognizer.state==UIGestureRecognizerStateEnded){
if (self.interacting) {
if (progress>0.5) {
[self finishInteractiveTransition];
}else{
[self cancelInteractiveTransition];
}
self.interacting = NO;
}
}
} @end
.m
2.3、使用自定义转场动画
1》设置代理(以模态弹出为例)设置目标控制器的 transitioningDelegate
- (IBAction)present:(id)sender {
PresentedViewController *vc = [[PresentedViewController alloc] init];
vc.transitioningDelegate = self;
[_transitionController wireToViewController:vc];
[self presentViewController:vc animated:YES completion:nil];
}
附加:Navigation和TabBar代理设置(self.delegate = self)
2》实现UIViewControllerTransitioningDelegate代理方法
//设置弹出时动画协议
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
//设置消失时动画协议
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;
//设置消失时手势协议
- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator;
vc1的.m文件:
#import "PresentingViewController.h"
#import "CustomTransform.h"
#import "CustonInteractive.h"
#import "PresentedViewController.h" #import "SecondTransform.h"
#import "SecondInteractive.h"
@interface PresentingViewController ()<UIViewControllerTransitioningDelegate,UINavigationControllerDelegate,UITabBarControllerDelegate>{
SecondTransform *_presentAnimation;
SecondInteractive *_transitionController;
} @end @implementation PresentingViewController - (void)viewDidLoad {
[super viewDidLoad];
_presentAnimation = [SecondTransform new];
_transitionController = [SecondInteractive new];
// Do any additional setup after loading the view from its nib.
}
- (IBAction)present:(id)sender {
PresentedViewController *vc = [[PresentedViewController alloc] init];
vc.transitioningDelegate = self;
[_transitionController wireToViewController:vc];
[self presentViewController:vc animated:YES completion:nil];
}
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
return _presentAnimation;
} - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
return [SecondTransform makeWithTransitionType:PresentTransformAnimationTypeDismissed];
} -(id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator {
return _transitionController.isInterraction ? _transitionController : nil;
}
@end
.m
Navigation和TabBar的代理方法:
#pragma mark---UINavigationControllerDelegate
/*
- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController NS_AVAILABLE_IOS(7_0); - (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
*/ #pragma mark-UITabBarControllerDelegate
/*
- (nullable id <UIViewControllerInteractiveTransitioning>)tabBarController:(UITabBarController *)tabBarController
interactionControllerForAnimationController: (id <UIViewControllerAnimatedTransitioning>)animationController NS_AVAILABLE_IOS(7_0); - (nullable id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
animationControllerForTransitionFromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
*/
Navigation和TabBar的delegate
iOS开发自定义转场动画的更多相关文章
- iOS开发——自定义转场动画
首先是UIPresentationController,这个控制器给modal新的viewController提供了下一步的view和转场的管理,从一个viewController被modal出来到被 ...
- iOS CATransition 自定义转场动画
https://www.jianshu.com/p/39c051cfe7dd CATransition CATransition 是CAAnimation的子类(如下图所示),用于控制器和控制器之间的 ...
- 一行代码实现自定义转场动画--iOS自定义转场动画集
WXSTransition 这款非常不错,力推 这是作者源码简书地址: http://www.jianshu.com/p/fd3154946919 这是作者源码github地址 https://git ...
- iOS开发UI篇—核心动画(转场动画和组动画)
转自:http://www.cnblogs.com/wendingding/p/3801454.html iOS开发UI篇—核心动画(转场动画和组动画) 一.转场动画简单介绍 CAAnimation的 ...
- iOS自定义转场动画的实现
iOS中熟悉的是导航栏中的push和pop这两种动画效果,在这里我们可以自己实现自己想要的一些转场动画 下面是我自己创建转场动画的过程 1.新建一个文件继承自NSObject ,遵循协议UIViewC ...
- iOS 自定义转场动画
代码地址如下:http://www.demodashi.com/demo/12955.html 一.总效果 本文记录分享下自定义转场动画的实现方法,具体到动画效果:新浪微博图集浏览转场效果.手势过渡动 ...
- iOS 自定义转场动画浅谈
代码地址如下:http://www.demodashi.com/demo/11612.html 路漫漫其修远兮,吾将上下而求索 前记 想研究自定义转场动画很久了,时间就像海绵,挤一挤还是有的,花了差不 ...
- iOS自定义转场动画实战讲解
iOS自定义转场动画实战讲解 转场动画这事,说简单也简单,可以通过presentViewController:animated:completion:和dismissViewControllerA ...
- Swift开发小技巧--自定义转场动画
自定义转场动画 个人理解为重写了被弹出控制器的modal样式,根据自己的样式来显示modal出来的控制器 例:presentViewController(aVC, animated: true, co ...
随机推荐
- 【POJ】1611 The Suspects
题目链接:http://poj.org/problem?id=1611 题意:有学生感染了SARS.一个学生可以加入很多小组.n个学生m个小组,每个小组有k个组内成员,后跟着k个成员的组内编号.让你求 ...
- 面试系列38 分库分表之后,id主键如何处理?
(1)数据库自增id 这个就是说你的系统里每次得到一个id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个id.拿到这个id之后再往对应的分库分表里去写入. 这个方案 ...
- css3的选择器
先来做一下准备工作 页面的效果: 看到上面的框框了吗?我们就是通过给这些框框添加背景色的方式,来让大家,了解css3的选择器的效果,下面正式开始: 关联选择器 E1~E2 选择 E1 后面的兄弟 E2 ...
- 在普通类中获取Spring管理的bean
1.在项目中添加下面的类: import org.springframework.context.ApplicationContext; import org.springframework.cont ...
- mysql sql的分类、运算符、常用的数据类型
SQL (结构化查询语言)的分类 DML(数据操作语言),关键字 insert,update,delete, DCL(数据控制语言),控制权限,grand,revoke 授权,回收 DDL(数据定义语 ...
- 2018-2-13-win10-uwp-上传Nuget-让别人用我们的库
title author date CreateTime categories win10 uwp 上传Nuget 让别人用我们的库 lindexi 2018-2-13 17:23:3 +0800 2 ...
- SpringBoot Redis 订阅发布
一 配置application.yml spring: redis: jedis: pool: max-active: 10 min-idle: 5 max-idle: 10 max-wait: 2 ...
- heartbeat 高可用
转载来自 http://www.cnblogs.com/liwei0526vip/p/6391833.html 使用HeartBeat实现高可用HA的配置过程详解 一.写在前面 HA即(high av ...
- JavaScript - window对象相关
1 . window对象常用方法 : 写法 : window.方法() 注意 : window可以省略不写 alert(), confirm(), prompt()是JavaScript提供和用户交互 ...
- 重磅发布: 阿里云WAF日志实时分析上线 (含视频)
摘要: 阿里云WAF与日志服务打通,对外开发Web访问与攻击日志.提供近实时的网站具体的日志自动采集存储.并提供基于日志服务的查询分析.报表报警.下游计算对接与投递的能力. 背景 Web攻击形势 互联 ...