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 ...
随机推荐
- Linux ls 命令实现(简化版)
在学习linux系统编程的时候,实现了ls命令的简化版本号. 实现的功能例如以下: 1. 每种文件类型有自己的颜色 (- 普通文件, d 文件夹文件, l 链接文件. c 字符设备文件. b 快设备文 ...
- eclipse新建maven项目和聚合项目
1.new maven project : next 2.勾选 create a simple project : next 3.Group Id:项目的包路径 如com.jiayou.zjl, ...
- 2019-8-31-C#-通过编程的方法在桌面创建回收站快捷方式
title author date CreateTime categories C# 通过编程的方法在桌面创建回收站快捷方式 lindexi 2019-08-31 16:55:58 +0800 201 ...
- JS事件 加载事件(onload)注意:1. 加载页面时,触发onload事件,事件写在<body>标签内。 2. 此节的加载页面,可理解为打开一个新页面时。
加载事件(onload) 事件会在页面加载完成后,立即发生,同时执行被调用的程序. 注意:1. 加载页面时,触发onload事件,事件写在<body>标签内. 2. 此节的加载页面,可理解 ...
- XSS攻击原理
本文转载的地址:http://www.2cto.com/Article/201209/156182.html Xss(cross-site scripting)攻击指的是攻击者往Web页面里插入恶意h ...
- SpringBoot 非web项目简单架构
1.截图 2.DemoService package com.github.weiwei02.springcloudtaskdemo; import org.springframework.beans ...
- Windows cd
显示当前目录名或改变当前目录. CHDIR [/D] [drive:][path]CHDIR [..]CD [/D] [drive:][path]CD [..] .. 指定要改成父目录. 键入 C ...
- AFO成功
在dcoi一年多,还是发生了不少事情. 过程中也有些小遗憾,有做错的事情,有搞砸的事情,有没办法挽回的事情,这种没法读档的辣鸡游戏也是无可奈何的.对所有被我搞砸的事情说声对不起啦,至少在下一次的时候, ...
- hibernate_04_hibernate多对多的关系映射
1.实体类的多对多的关系映射 一个用户可以有多个角色 User.java public class User { private Long user_id; private String user_c ...
- System.Web.Mvc.Controller.cs
ylbtech-System.Web.Mvc.Controller.cs 1.程序集 System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicK ...