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 ...
随机推荐
- 最短路(模板Dtra
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const i ...
- 2008年国外50个最佳CSS设计欣赏
这50个CSS网站是由WebDesignerWall评选出来的,很具参考价值.我们在欣赏的同时,也能从中吸取很多灵感,也能从它们的源代码中学习更高级的CSS技术.今年,越来越多的设计师开始使用超大的背 ...
- java 3des加密问题记录
3des加密有不同的加密模式和填充模式,这个网上很多不多说了,只要保证加解密的时候加密模式和填充模式保持一致就可以了 首先对于密钥的生成,java中有2种方式: 1.第一种,采用ECB模式和不填充模式 ...
- kaggle 实战 (1): PCA + KNN 手写数字识别
文章目录 加载package read data PCA 降维探索 选择50维度, 拆分数据为训练集,测试机 KNN PCA降维和K值筛选 分析k & 维度 vs 精度 预测 生成提交文件 本 ...
- sikuli+eclipse对于安卓app自动化测试的应用(第一次写博客,有些语言还不太专业,望海涵)
Sikuli是什么? 下面是来自于官网的介绍:Sikuli is a visual technology to automate and test graphical user interfaces ...
- MongoDB使用固定集合
MongoDB中的固定集合:大小是固定的,类似于循环队列,如果没有空间了,最老的文档会被删除以释放空间,新插入的会占据这块空间. 1.固定集合(oplog) oplog是一个典型的固定集合,因为其大小 ...
- BlueHost主机建站方案怎样选择?
BlueHost是知名美国主机商,近年来BlueHost不断加强中国市场客户的用户体验,提供多种主机租用方案,基本能够满足各类网站建设需求.下面就和大家介绍一下建站应该怎样选择主机. 1.中小型网站 ...
- Google Projectsheet Planning 插件的WBS
生成 WBS的序列號 在 Sldebar中的 "WBS" 按鈕: "< WBS" 取消下級目錄 "WBS >" 生成下級目錄 G ...
- arc098E Range Minimum Queries
题意:给你一个n个数的数组,每次能够选取连续的长度为K的子序列,取出其中任意一个最小元素. 一共操作Q次.问取出的元素中Max-Min最小是多少? 标程: #include<bits/stdc+ ...
- php 垃圾回收机制 转载
PHP的基本GC概念PHP语言同其他语言一样,具有垃圾回收机制.那么今天我们要为大家讲解的内容就是关于PHP垃圾回收机制的相关问题.希望对大家有所帮助.PHP strtotime应用经验之谈PHP m ...