iOS核心动画CoreAnimation系统进阶(自定义转场动画)
程序员文章站
2022-04-11 13:19:30
...
想要实现自定义转场动画,需要分两个步骤
一.实现相关协议
@interface CustomTransitionViewController ()<UINavigationControllerDelegate>
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationController.delegate = self;
}
//告诉nav,想自己自定义一个转场
-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
if (operation == UINavigationControllerOperationPush) {
WTCircleTransition *trans =[WTCircleTransition new];
return trans;
}
return nil;
}
二.做动画
创建WTCircleTransition协议类
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface WTCircleTransition : NSObject<UIViewControllerAnimatedTransitioning>
@end
实现UIViewControllerAnimatedTransitioning中的协议
WTCircleTransition.m
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
return .8f;
}
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
//1.持有transitionContext上下文
_context = transitionContext;
//2.获取view的容器
UIView *containerView = [transitionContext containerView];
//3.初始化toVc,把toVc的view添加到容器view
UIViewController *toVc =[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
//4.添加动画
/*
拆分动画
4.1 2个圆(大小圆的中心点一致)
4.2 贝塞尔
4.3 蒙版
*/
UIButton *btn;
CustomTransitionViewController * VC1;
SecondViewController * VC2;
if (_isPush) {
VC1 =[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
VC2 = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
btn = VC1.customTransitionBtn;
}else{
VC2 =[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
VC1 = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
btn = VC2.backBtn;
}
[containerView addSubview:VC1.view];
[containerView addSubview:VC2.view];
//5.画出小圆
UIBezierPath *smallPath =[UIBezierPath bezierPathWithOvalInRect:btn.frame];//内切圆
CGPoint centerP;
centerP = btn.center;
//6.求大圆半径 勾股定理
CGFloat radius;
CGFloat y = CGRectGetHeight(toVc.view.bounds)-CGRectGetMaxY(btn.frame)+CGRectGetHeight(btn.bounds)/2;
CGFloat x = CGRectGetWidth(toVc.view.bounds)-CGRectGetMaxX(btn.frame)+CGRectGetWidth(btn.bounds)/2;
if (btn.frame.origin.x >CGRectGetWidth(toVc.view.bounds)/2) {
//位于1,4象限
if (CGRectGetMaxY(btn.frame)< CGRectGetHeight(toVc.view.bounds)/2) {
//第一象限
//sqrtf(求平方根)
radius = sqrtf(btn.center.x *btn.center.x +y*y);
}else{
//第四象限
radius = sqrtf(btn.center.x * btn.center.x + btn.center.y*btn.center.y);
}
}else{
if (CGRectGetMaxY(btn.frame)<CGRectGetHeight(toVc.view.frame)) {
//第二象限
radius = sqrtf(x*x+y*y);
}else{
//第三象限
radius = sqrtf(x*x + btn.center.y*btn.center.y);
}
}
//7.画大圆
UIBezierPath * bigPath = [UIBezierPath bezierPathWithArcCenter:centerP radius:radius startAngle:0 endAngle:2*M_PI clockwise:YES];
//8.
CAShapeLayer *shapeLayer =[CAShapeLayer layer];
if (_isPush) {
shapeLayer.path = bigPath.CGPath;
} else{
shapeLayer.path = smallPath.CGPath;
}
//9.添加蒙版
// [toVc.view.layer addSublayer:shapeLayer];
UIViewController *VC;
if (_isPush) {
VC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
}else{
VC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
}
VC.view.layer.mask = shapeLayer;
//10.给layer添加动画
CABasicAnimation *anim =[CABasicAnimation animationWithKeyPath:@"path"];
if (_isPush) {
anim.fromValue = (id)smallPath.CGPath;
}else{
anim.fromValue = (id)bigPath.CGPath;
}
//重要,动画时间要和转场时间一致
anim.duration = [self transitionDuration:transitionContext];
anim.delegate = self;
[shapeLayer addAnimation:anim forKey:nil];
}
#pragma mark - CAAnimationDelegate
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
[_context completeTransition:YES];
//去掉蒙版
if (_isPush) {
UIViewController * toVc =[_context viewControllerForKey:UITransitionContextToViewControllerKey];
toVc.view.layer.mask = nil;
}else{
UIViewController * toVc =[_context viewControllerForKey:UITransitionContextFromViewControllerKey];
toVc.view.layer.mask = nil;
}
}
大圆半径
勾股定理求半径
判断象限
在做自定义转场动画时,我们需要进行几个步骤:
- 实现相关协议 push/pop motal segue
- 添加实现了UIViewControllerAnimatedTransitioning的类
- 在类里面实现动画协议,然后添加转场动画
- 告诉上下文,动画完成
总结:自定义切换并不会改变VC的组织结构,只是负责提供了view的效果
实现效果:
推荐阅读
-
iOS自定义转场动画的几种情况
-
IOS实战之自定义转场动画详解
-
深入学习iOS7自定义导航转场动画
-
iOS CAAnimation之CATransition(自定义转场动画)
-
IOS开发教程第一季之UI进阶day8合并IOS学习019--敲击、长按、轻扫、旋转,CALayer、锚点,CADisolayLink刷新,核心动画,关键帧动画,组动画,转场动画,画板案例
-
iOS 自定义转场动画篇
-
iOS自定义转场动画的几种情况
-
iOS CAAnimation之CATransition(自定义转场动画)
-
iOS出门必备之CoreAnimation(核心动画)
-
iOS核心动画CoreAnimation系统进阶(转场动画&组动画)