iOS自定义转场动画

发布于:2021-10-16 18:45:37

iOS7推出了新的转场动画API,以协议id、id方式开放给开发者,不同于代理、类别,这样更易于我们自定义动画,更加灵活。下面介绍一下自定义转场动画




自定义转场动画步骤:


1:创建动画管理类ZZFTransition,实现UIViewControllerAnimatedTransitioning,CAAnimationDelegate协议

自定义动画的主要代码都在管理类中实现,在需要动画的时候调用这个类的方法即可。


ZZFTransition.h





#import #import

typedef NS_ENUM(NSUInteger, ZZFTransitionType) { ZZFTransitionTypePush, ZZFTransitionTypePop,};

@interface ZZFTransition : NSObject+(ZZFTransition *)transitionAnimationWithType:(ZZFTransitionType)type;@end复制代码




定义枚举类型ZZFTransitionType,包含两个值,分别是push类型和pop类型。


定义类方法transitionAnimationWithType,传入动画类型,返回实例对象。


ZZFTransition.m





+(ZZFTransition *)transitionAnimationWithType:(ZZFTransitionType)type{
ZZFTransition *transition = [[ZZFTransition alloc]init];
transition.type = type;
return transition;
}


复制代码



在.m文件中实现transitionAnimationWithType类方法,初始化实例对象,设置动画类型,返回对象。


2:实现UIViewControllerAnimatedTransitioning协议中的方法




-(NSTimeInterval)transitionDuration:(id)transitionContext{
return 3;
}
-(void)animateTransition:(id)transitionContext{

self.transitionContext = transitionContext;

switch (_type) {
case ZZFTransitionTypePush:
{
[self pushAnimation:transitionContext];
}
break;

case ZZFTransitionTypePop:
{
[self popAnimation:transitionContext];
}
break;
}
}


复制代码



-(NSTimeInterval)transitionDuration:(id)transitionContext;这个方法返回转场动画执行的时间。


-(void)animateTransition:(id)transitionContext;在这个方法内部实现动画的主要代码。


这里根据创建管理对象的时候传进来的动画类型,来分别处理不同的动画逻辑。把push和pop的动画实现放到一个方法中去,这里的代码更简洁。





- (void)pushAnimation:(id)transitionContext{
// 获得即将消失的vc的v
UIView *fromeView = [transitionContext viewForKey:UITransitionContextFromViewKey];
// 获得即将出现的vc的v
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
// 获得容器view
UIView *containerView = [transitionContext containerView];
[containerView addSubview:fromeView];
[containerView addSubview:toView];
UIBezierPath *startBP = [UIBezierPath bezierPathWithOvalInRect:CGRectMake((containerView.frame.size.width)/2, (containerView.frame.size.height)/2, 12, 12)];
CGFloat radius = containerView.frame.size.height - 100;
UIBezierPath *finalBP = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(150 - radius, 150 -radius, radius*2, radius*2)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = finalBP.CGPath;
toView.layer.mask = maskLayer;
//执行动画
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.fromValue = (__bridge id _Nullable)(startBP.CGPath);
animation.toValue = (__bridge id _Nullable)(finalBP.CGPath);
animation.duration = [self transitionDuration:transitionContext];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.delegate = self;
[maskLayer addAnimation:animation forKey:@"path"];
}


复制代码



参数transitionContext是执行动画的上下文,里面包含动画执行所需要的所有元素。


通过键值的方式,从上下文对象中可以的到需要执行动画的上一个VC和view,下一个VC和view。


UITransitionContextFromViewKey? 即将消失的view


UITransitionContextToViewKey? 即将出现的view


UITransitionContextFromViewControllerKey? 即将消失的控制器


UITransitionContextToViewControllerKey? 即将出现的控制器


然后通过上下文的containerView方法可以得到一个容器view,所有的动画都是在这个容器view内进行的,所以需要把fromView和toView都加入到containerView中。


下边用贝塞尔曲线画两个圆,然后用CABasicAnimation执行从小圆到大圆的动画。


到这里一个自定义的push动画就完成了,下边是使用的方法。


3:自定义动画的使用

在需要执行自定义动画的控制器中,遵守UINavigationControllerDelegate协议,并实现-(id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC;代理方法。


在执行push或pop操作时,这个代理方法会回调,在方法内部拿到跳转的动画类型,然后执行自己的动画代码就可以实现自定义转场动画。





-(id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
if (operation == UINavigationControllerOperationPush) {
ZZFTransition *pushTranstion = [ZZFTransition transitionAnimationWithType:ZZFTransitionTypePush];
return pushTranstion;
}
return nil;
}

复制代码



这里只实现了push,要实现pop自定义动画,同理。


4:注意点

执行push动画后,可以发现一个问题,界面的所有交互失效了,是因为执行动画时控制器view上加了遮罩layer,在动画执行完成后把遮罩去掉就可以了。


-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
[self.transitionContext completeTransition:YES];
//清除相应控制器视图的mask
[self.transitionContext viewForKey:UITransitionContextFromViewKey].layer.mask = nil;
[self.transitionContext viewForKey:UITransitionContextToViewKey].layer.mask = nil;
}


复制代码




转载于:https://juejin.im/post/5cad5c38f265da038c01f889






相关资源:ios-自定义Model的转场动画.zip

相关推荐

最新更新

猜你喜欢