<span style="color:#2f2f2f">大家都知道从iOS7开始,苹果就提供了自定义转场的API,模态推送present和dismiss、导航控制器push和pop、标签控制器的控制器切换都可以自定义转场了,</span>
/** CATransition
*
* @see http://www.dreamingwish.com/dream-2012/the-concept-of-coreanimation-programming-guide.html
* @see http://geeklu.com/2012/09/animation-in-ios/
*
* CATransition 常用设置及属性注解如下:
*/
CATransition *animation = [CATransitionanimation];
/** delegate
*
* 动画的代理,如果你想在动画开始和结束的时候做一些事,可以设置此属性,它会自动回调两个代理方法.
*
* @see CAAnimationDelegate (按下command键点击)
*/
animation.delegate =self;
/** duration
*
* 动画持续时间
*/
animation.duration = duration;
/** timingFunction
*
* 用于变化起点和终点之间的插值计算,形象点说它决定了动画运行的节奏,比如是均匀变化(相同时间变化量相同)还是
* 先快后慢,先慢后快还是先慢再快再慢.
*
* 动画的开始与结束的快慢,有五个预置分别为(下同):
* kCAMediaTimingFunctionLinear 线性,即匀速
* kCAMediaTimingFunctionEaseIn 先慢后快
* kCAMediaTimingFunctionEaseOut 先快后慢
* kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
* kCAMediaTimingFunctionDefault 实际效果是动画中间比较快.
*/
/** timingFunction
*
* 当上面的预置不能满足你的需求的时候,你可以使用下面的两个方法来自定义你的timingFunction
* 具体参见下面的URL
*
*
* + (id)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
*
* - (id)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
*/
animation.timingFunction = [CAMediaTimingFunctionfunctionWithName:timingFunction];
/** fillMode
*
* 决定当前对象过了非active时间段的行为,比如动画开始之前,动画结束之后.
* 预置为:
* kCAFillModeRemoved 默认,当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
* kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
* kCAFillModeBackwards 和kCAFillModeForwards相对,具体参考上面的URL
* kCAFillModeBoth kCAFillModeForwards和kCAFillModeBackwards在一起的效果
*/
animation.fillMode =kCAFillModeForwards;
/** removedOnCompletion
*
* 这个属性默认为YES.一般情况下,不需要设置这个属性.
*
* 但如果是CAAnimation动画,并且需要设置 fillMode 属性,那么需要将 removedOnCompletion设置为NO,否则
* fillMode无效
*/
// animation.removedOnCompletion = NO;
/** type
*
* 各种动画效果 其中除了'fade', `moveIn', `push' , `reveal' ,其他属于私有的API(我是这么认为的,可以点进去看下注释).
* ↑↑↑上面四个可以分别使用'kCATransitionFade', 'kCATransitionMoveIn', 'kCATransitionPush', 'kCATransitionReveal'来调用.
* @"cube" 立方体翻滚效果
* @"moveIn" 新视图移到旧视图上面
* @"reveal" 显露效果(将旧视图移开,显示下面的新视图)
* @"fade" 交叉淡化过渡(不支持过渡方向) (默认为此效果)
* @"pageCurl" 向上翻一页
* @"pageUnCurl" 向下翻一页
* @"suckEffect" 收缩效果,类似系统最小化窗口时的神奇效果(不支持过渡方向)
* @"rippleEffect" 滴水效果,(不支持过渡方向)
* @"oglFlip" 上下左右翻转效果
* @"rotate" 旋转效果
* @"push"
* @"cameraIrisHollowOpen" 相机镜头打开效果(不支持过渡方向)
* @"cameraIrisHollowClose" 相机镜头关上效果(不支持过渡方向)
*/
/** type
*
* kCATransitionFade 交叉淡化过渡
* kCATransitionMoveIn 新视图移到旧视图上面
* kCATransitionPush 新视图把旧视图推出去
* kCATransitionReveal 将旧视图移开,显示下面的新视图
*/
animation.type = type;
/** subtype
*
* 各种动画方向
*
* kCATransitionFromRight; 同字面意思(下同)
* kCATransitionFromLeft;
* kCATransitionFromTop;
* kCATransitionFromBottom;
分别对应上面四个方向
@“fromRight”
@“fromLeft”
@"fromTop"
@"fromBottom"
*/
/** subtype
*
* 当type为@"rotate"(旋转)的时候,它也有几个对应的subtype,分别为:
* 90cw 逆时针旋转90°
* 90ccw 顺时针旋转90°
* 180cw 逆时针旋转180°
* 180ccw 顺时针旋转180°
*/
/**
* type与subtype的对应关系(必看),如果对应错误,动画不会显现.
*
* @see http://iphonedevwiki.net/index.php/CATransition
*/
animation.subtype = subType;
/**
* 所有核心动画和特效都是基于CAAnimation,而CAAnimation是作用于CALayer的.所以把动画添加到layer上.
* forKey 可以是任意字符串.
*/
[theView.layeraddAnimation:animationforKey:nil];
================
CATransition *animation = [CATransitionanimation];//创建动画
[animation setDuration:0.35f];//动画持续时间
[animation setFillMode:kCAFillModeForwards];//决定当前对象过了非active时间段的行为,比如动画开始之前,动画结束之后.
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];//
用于变化起点和终点之间的插值计算,形象点说它决定了动画运行的节奏,比如是均匀变化(相同时间变化量相同)还是
* 先快后慢,先慢后快还是先慢再快再慢.-----这个也可以自定义
[animation setType:kCATransitionPush];//设置动画的效果
[animation setSubtype:kCATransitionFromTop];//设置动画的方向
[view.layeraddAnimation:animationforKey:nil];//动画添加到layer层
=======================
/* Common transition types. */types确定动画的类型,下面是系统提供的
CA_EXTERN NSString *const kCATransitionFade//退去
CA_AVAILABLE_STARTING (10.5,2.0,9.0,2.0);
CA_EXTERN NSString *const kCATransitionMoveIn//进来
CA_AVAILABLE_STARTING (10.5,2.0,9.0,2.0);
CA_EXTERN NSString *const kCATransitionPush//推出去
CA_AVAILABLE_STARTING (10.5,2.0,9.0,2.0);
CA_EXTERN NSString *const kCATransitionReveal//逐步展现
CA_AVAILABLE_STARTING (10.5,2.0,9.0,2.0);
/* Common transition subtypes. *///subtypes确定动画的方向
CA_EXTERN NSString *const kCATransitionFromRight//从右边过来
CA_AVAILABLE_STARTING (10.5,2.0,9.0,2.0);
CA_EXTERN NSString *const kCATransitionFromLeft//从左边过来
CA_AVAILABLE_STARTING (10.5,2.0,9.0,2.0);
CA_EXTERN NSString *const kCATransitionFromTop//从上边过来
CA_AVAILABLE_STARTING (10.5,2.0,9.0,2.0);
CA_EXTERN NSString *const kCATransitionFromBottom//从底部过来
CA_AVAILABLE_STARTING (10.5,2.0,9.0,2.0);
===================
举例:系统的
+ (void)animationRevealFromBottom:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setType:kCATransitionReveal];
[animation setSubtype:kCATransitionFromBottom];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseIn]];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationRevealFromTop:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setType:kCATransitionReveal];
[animation setSubtype:kCATransitionFromTop];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationRevealFromLeft:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setType:kCATransitionReveal];
[animation setSubtype:kCATransitionFromLeft];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationRevealFromRight:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setType:kCATransitionReveal];
[animation setSubtype:kCATransitionFromRight];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationEaseIn:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setType:kCATransitionFade];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseIn]];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationEaseOut:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setType:kCATransitionFade];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationPushUp:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromTop];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationPushDown:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromBottom];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationPushLeft:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationPushRight:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromRight];
[view.layeraddAnimation:animationforKey:nil];
}
// presentModalViewController
+ (void)animationMoveUp:(UIView *)view duration:(CFTimeInterval)duration
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:duration];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[animation setType:kCATransitionMoveIn];
[animation setSubtype:kCATransitionFromTop];
[view.layeraddAnimation:animationforKey:nil];
}
// dissModalViewController
+ (void)animationMoveDown:(UIView *)view duration:(CFTimeInterval)duration
{
CATransition *transition = [CATransitionanimation];
transition.duration =0.4;
transition.timingFunction = [CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type =kCATransitionReveal;
transition.subtype =kCATransitionFromBottom;
[view.layeraddAnimation:transitionforKey:nil];
}
+ (void)animationMoveLeft:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:kCATransitionMoveIn];
[animation setSubtype:kCATransitionFromLeft];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationMoveRight:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:kCATransitionMoveIn];
[animation setSubtype:kCATransitionFromRight];
[view.layeraddAnimation:animationforKey:nil];
}
=================举例私有的动画效果
+ (void)animationFlipFromTop:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"oglFlip"];
[animation setSubtype:@"fromTop"];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationFlipFromBottom:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"oglFlip"];
[animation setSubtype:@"fromBottom"];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationCubeFromLeft:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"cube"];
[animation setSubtype:@"fromLeft"];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationCubeFromRight:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"cube"];
[animation setSubtype:@"fromRight"];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationCubeFromTop:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"cube"];
[animation setSubtype:@"fromTop"];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationCubeFromBottom:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"cube"];
[animation setSubtype:@"fromBottom"];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationSuckEffect:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"suckEffect"];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationRippleEffect:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"rippleEffect"];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationCameraOpen:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"cameraIrisHollowOpen"];
[animation setSubtype:@"fromRight"];
[view.layeraddAnimation:animationforKey:nil];
}
+ (void)animationCameraClose:(UIView *)view
{
CATransition *animation = [CATransitionanimation];
[animation setDuration:0.35f];
[animation setFillMode:kCAFillModeForwards];
[animation setTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseOut]];
[animation setType:@"cameraIrisHollowClose"];
[animation setSubtype:@"fromRight"];
[view.layeraddAnimation:animationforKey:nil];
}
===============================自定义转场动画
-
我们需要自定义一个遵循的
<UIViewControllerAnimatedTransitioning>
协议的动画过渡管理对象,并实现两个必须实现的方法://返回动画事件 - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext; //所有的过渡动画事务都在这个方法里面完成 - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
- 我们还需要自定义一个继承于
UIPercentDrivenInteractiveTransition(这是一个继承自NSObject的类)
的手势过渡管理对象,我把它成为百分比手势过渡管理对象,因为动画的过程是通过百分比控制的; -
成为相应的代理,实现相应的代理方法,返回我们前两步自定义的对象就OK了 !
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, PDAnimationType){
animationTypePresent = 0,
animationTypeDismiss ,
animationTypePush ,
animationTypePop,
};
NS_ASSUME_NONNULL_BEGIN
@interface PDAnimatorBaseTransition : NSObject<UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign)PDAnimationType animationType;
@property (nonatomic, strong)UIView *containerView;
@property (nonatomic, strong)UIViewController *from;
@property (nonatomic, strong)UIViewController *to;
@property (nonatomic, strong)UIView *fromView;
@property (nonatomic, strong)UIView *toView;
@property (nonatomic, weak)id <UIViewControllerContextTransitioning> transitionContext;
@end
NS_ASSUME_NONNULL_END
********
#import "PDAnimatorBaseTransition.h"
@implementation PDAnimatorBaseTransition
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{
return 1.f;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
_transitionContext = transitionContext;
_containerView = [transitionContext containerView];
_from = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
_to = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
if([transitionContext respondsToSelector:@selector(viewForKey:)]){
_fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
_toView = [transitionContext viewForKey:UITransitionContextToViewKey];
}else{
_fromView = _from.view;
_toView = _to.view;
}
if(self.animationType == animationTypePresent){
[self animationPresent];
}else if (self.animationType == animationTypeDismiss){
[self animationDismiss];
}else if (self.animationType == animationTypePop){
[self animationPop];
}else{
[self animationPush];
}
}
#pragma mark -optional
//动画结束时回调
- (void)animationEnded:(BOOL) transitionCompleted{
}
- (void)animationPresent{
}
- (void)animationDismiss{
}
- (void)animationPop{
}
- (void)animationPush{
}
@end
********** present
/**
//然后我们在需要present的地方实现UIViewControllerTransitioningDelegate的代理方法
//- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
//
// PDAnimationPresentTransition *animationTransition = [[PDAnimationPresentTransition alloc] init];
// animationTransition.animationType = animationTypePresent;
// return animationTransition;
//}
//
//- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
//
// PDAnimationPresentTransition *animationTransition = [[PDAnimationPresentTransition alloc] init];
// animationTransition.animationType = animationTypePresent;
// return animationTransition;
//}
**/
#import "PDAnimatorBaseTransition.h"
NS_ASSUME_NONNULL_BEGIN
@interface PDAnimationPresentTransition : PDAnimatorBaseTransition
@end
NS_ASSUME_NONNULL_END
***********
#import "PDAnimationPresentTransition.h"
@implementation PDAnimationPresentTransition
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{
return 1.f;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
[super animateTransition:transitionContext];
}
- (void)animationPresent{
NSTimeInterval duration = [self transitionDuration:self.transitionContext];
__weak typeof(self) weakSelf = self;
self.toView.frame = [self.transitionContext initialFrameForViewController:self.to];
self.fromView.frame = [self.transitionContext initialFrameForViewController:self.from];
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, 0.001, 0.001);
//transform =CGAffineTransformMakeRotation(M_PI/2);
self.toView.layer.affineTransform = transform;
[self.containerView addSubview:self.toView];
self.toView.alpha = 0.0;
[UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.6 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.toView.layer.affineTransform = CGAffineTransformIdentity;
self.toView.frame = [self.transitionContext finalFrameForViewController:self.to];
self.toView.alpha = 1.0;
} completion:^(BOOL finished){
BOOL wasCancelled = [weakSelf.transitionContext transitionWasCancelled];
[weakSelf.transitionContext completeTransition:!wasCancelled];
}];
}
@end
********push
/**
//然后我们在需要push的地方实现UINavigationControllerDelegate的协议方法:
//
//- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
//animationControllerForOperation:(UINavigationControllerOperation)operation
//fromViewController:(UIViewController *)fromVC
//toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0){
//
// PDAnimatorPUshPopTransition *animationTransition = [[PDAnimatorPUshPopTransition alloc] init];
// if(operation == UINavigationControllerOperationPush){
//
// animationTransition.animationType = animationTypePush;
// }else if (operation == UINavigationControllerOperationPop){
//
// animationTransition.animationType = animationTypePop;
// }
//
// NSArray *indexPaths = [self.collectionView indexPathsForSelectedItems];
// if (indexPaths.count == 0) {
// return nil;
// }
//
// NSIndexPath *selectedIndexPath = indexPaths[0];
// UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:selectedIndexPath];
//
// // 一定要加上convertPoint:toView:操作
// animationTransition.itemCenter = [self.collectionView convertPoint:cell.center toView:self.view];
// animationTransition.itemSize = cell.frame.size;
// animationTransition.imageName = [NSString stringWithFormat:@"%ld", (long)selectedIndexPath.item];
//
// return animationTransition;
//}
**/
#import "PDAnimatorBaseTransition.h"
#import <UIKit/UIKit.h>
@interface PDAnimatorPUshPopTransition : PDAnimatorBaseTransition
@property (nonatomic, assign)CGPoint itemCenter;
@property (nonatomic, assign)CGSize itemSize;
@property (nonatomic, strong)NSString *imageName;
@end
******
#import "PDAnimatorPUshPopTransition.h"
@implementation PDAnimatorPUshPopTransition
- (instancetype)init{
self = [super init];
if(self){
}
return self;
}
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{
return 5.f;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
[super animateTransition:transitionContext];
}
- (void)animationPush{
NSTimeInterval duration = [self transitionDuration:self.transitionContext];
__weak typeof(self) weakSelf = self;
self.containerView.backgroundColor = [UIColor lightGrayColor];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 160)];
imageView.image = [UIImage imageNamed:self.imageName];
imageView.center = _itemCenter;
CGFloat initialScale = _itemSize.width / CGRectGetWidth(imageView.frame);
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, initialScale, initialScale);
transform = CGAffineTransformRotate(transform, M_PI);
imageView.layer.affineTransform = transform;
// imageView.transform = CGAffineTransformMakeScale(initialScale, initialScale);
[self.containerView addSubview:imageView];
self.toView.frame = [self.transitionContext finalFrameForViewController:self.to];
CGPoint finalCenter = self.toView.center;
self.toView.center = finalCenter;
self.toView.alpha = 0.0;
//这一句一定要
[self.containerView addSubview:self.toView];
[UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{
imageView.layer.affineTransform = CGAffineTransformIdentity;
imageView.center = finalCenter;
self.fromView.alpha = 0.0;
self.containerView.backgroundColor = [UIColor redColor];
} completion:^(BOOL finished){
[imageView removeFromSuperview];
weakSelf.toView.alpha = 1.0f;
weakSelf.fromView.alpha = 1.0f;
[weakSelf.transitionContext completeTransition:![weakSelf.transitionContext transitionWasCancelled]];
}];
}
- (void)animationPop{
NSTimeInterval duration = [self transitionDuration:self.transitionContext];
__weak typeof(self) weakSelf = self;
self.toView.frame = [self.transitionContext finalFrameForViewController:self.to];
[self.containerView insertSubview:self.toView belowSubview:self.fromView];
self.fromView.alpha = 0.0;
self.fromView.backgroundColor = [UIColor clearColor];
[UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{
CGFloat initialScale = _itemSize.width / 200;
weakSelf.fromView.transform = CGAffineTransformMakeScale(initialScale, initialScale);
weakSelf.fromView.center = weakSelf.itemCenter;
weakSelf.toView.alpha = 1.0f;
} completion:^(BOOL finished){
weakSelf.fromView.alpha = 0.0f;
[weakSelf.transitionContext completeTransition:![weakSelf.transitionContext transitionWasCancelled]];
}];
}
@end