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 ...
随机推荐
- 2019-8-31-dotnet-数组自动转基类数组提示-Co-variant-array-conversion-是什么问题
title author date CreateTime categories dotnet 数组自动转基类数组提示 Co-variant array conversion 是什么问题 lindexi ...
- Dubbo的底层实现原理和机制
–高性能和透明化的RPC远程服务调用方案 –SOA服务治理方案 Dubbo缺省协议采用单一长连接和NIO异步通讯, 适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况
- css---5 only-child or nth-of-type
1 _nth-child系列 :nth-child(index) <!DOCTYPE html> <html lang="en"> <head> ...
- 最大流拆点——poj3281
/* 因为牛的容量为1,把牛拆点 按照s->f->cow->cow->d->t建图 */ #include<iostream> #include<cst ...
- react 组件的生命周期 超简版
组件从被创建到被销毁的过程称为组件的 生命周期: 通常,组件的生命周期可以被分为三个阶段:挂载阶段.更新阶段.卸载阶段: 一.挂载阶段 这个阶段组件被创建,执行初始化,并被挂载到DOM中,完成组件的第 ...
- (转)获取android手机内部存储空间和外部存储空间的参数 && 如何决定一个apk的安装位置
转:http://blog.csdn.net/zhandoushi1982/article/details/8560233 获取android文件系统的信息,需要Environment类和StatFs ...
- 阿里P8架构师谈:数据库分库分表、读写分离的原理实现,使用场景
本文转载自:阿里P8架构师谈:数据库分库分表.读写分离的原理实现,使用场景 为什么要分库分表和读写分离? 类似淘宝网这样的网站,海量数据的存储和访问成为了系统设计的瓶颈问题,日益增长的业务数据,无疑对 ...
- System.Web.UI.WebControls.FileUpload.cs
ylbtech-System.Web.UI.WebControls.FileUpload.cs 1. 程序集 System.Web, Version=4.0.0.0, Culture=neutral, ...
- 关于python3字符串中引号格式的看法,‘’,“”
关于字符串中引号格式的看法 在python3中,字符串统一使用: ' ' 或 " " 来表示,两者没有什么区别. 但是在使用的过程中,可以注意一下使用的方式,可以提高编程 ...
- Oracle一条数据多表连插
insert all into T_TRAIN_MARSHALLING <trim prefix="(GKEY," suffix=")" suffixOv ...