想写简书很久了 一直没时间 刚好项目做完了 现在来写篇简书吧 有很多不足之处希望大家多多指正批评 好 下面进入正题
先上效果图
这其实一个自定义push转场动画 关于转场动画 网上资料也很多 我现在贴出一篇我觉得写的很好的传送门
分析动画
先要了解几个概念 from 和 to 在代码中经常看到fromView和toView这类的
1.fromView表示当前视图
2.toView表示要跳转到的视图
我们似乎可以看到是fromView旋转了180° 其实不是这样的 我是这样处理的 先让toView旋转90° 然后此时fromView和头view形成了一个+形状 然后让fromView旋转90° 完成后 toView在旋转90° 这样就达到这个动画 当然要注意旋转的方向 这些在代码中有详细的注释
定义转场动画
首先定义一个遵循了UIViewControllerAnimatedTransitioning协议的类。并且实现下面2个方法
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext ;
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext;
第一个方法是返回转场的时间 第二个方法可以拿到转场的上下文(上下文大家很明白吧)这个上下文里面就包含我们转场需要的几乎所有元素 包括fromView fromVC toView 等等 然后我们这里写我们的动画的逻辑就可以了
需要注意的一点就是 我们要把push 和 pop的动画分开 所以我是这样处理的
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
switch (self.type) {
case XWPushTransitionManagerPush:
[self doPushAnimation:transitionContext];
break;
case XWPushTransitionManagerPop:
[self doPopAnimation:transitionContext];
break;
default:
break;
}
}
最后贴出我动画的逻辑
- (void)ThrerDPushAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
// 将要转场出来的view
UIView *toView =[transitionContext viewForKey:UITransitionContextToViewKey];
// 当前的view
UIView *formView = [transitionContext viewForKey:UITransitionContextFromViewKey];
// 转场的容器
UIView *contaniView = [transitionContext containerView];
contaniView.backgroundColor = [UIColor orangeColor];
CATransform3D percatier = CATransform3DIdentity;
// 设置m34 才有立体效果
percatier.m34 = -1.0/500;
//sublayerTranform
// 设置了父视图的sublayerTranform 子视图就都有这个transform
contaniView.layer.sublayerTransform = percatier;
[contaniView addSubview:toView];
[contaniView addSubview:formView];
//toview 默认旋转90
CATransform3D tranform1 = CATransform3DMakeRotation(-M_PI_2,0,1,0);
toView.layer.transform = tranform1;
// formview 的旋转角度 也是90 当formview旋转到90度时候 移除formview 并且toview开始动画
// 其实2个view 各自只旋转了90度
CATransform3D tranform2 = CATransform3DMakeRotation(M_PI_2,0,1,0);
// 关键帧动画
// StartTime:动画开始时间 取值0-1 指的是比例
// relativeDuration: 动画持续时间 取值0-1 指的是比例
[UIView animateKeyframesWithDuration:Time delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.5 animations:^{
// 当前的view 旋转90度
formView.layer.transform = tranform2;
}];
// formview 动画完成后 toView 进行动画
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{
toView.layer.transform = CATransform3DIdentity;
}];
} completion:^(BOOL finished) {
// 动画完成之后 要告诉系统 转场完成了 不然会出现bug
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
[formView removeFromSuperview];
}];
}
最后我们设置转场的代理并且设置UINavigationControllerDelegate 在代理方法中返回我们定义的类
#pragma mark -- 代理
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
//分pop和push两种情况分别返回动画过渡代理相应不同的动画操作
return [XWPushTransitionManager transitionWithType:operation == UINavigationControllerOperationPush ? XWPushTransitionManagerPush : XWPushTransitionManagerPop];
}
这里的UINavigationControllerOperation 这个枚举就是来区分是push 还是 pop 我们只需要返回对应的就可以拉
至此 我们的瞎搞push转场就完成了 当然你还得实现pop 这很简单 就动画的反向
手势驱动
最后我们在加上一个效果 就是手势驱动 啥事手势驱动呢 系统默认的 Push 和 Pop 动画都支持手势驱动 并且可以根据手势移动距离改变动画完成度 在iOS7以后 苹果为我们提供了一个UIPercentDrivenInteractiveTransition这个类 这个类就是专门来做手势驱动的 废话不多说 下面直接开搞
1.自定义一个类 继承于UIPercentDrivenInteractiveTransition 重写初始化方法 传入一个控制器(一般是push出来的vc)
2.个该vc添加一个Pan手势
3.在手势的监听方法里面计算手势移动的百分比 并使用 UIPercentDrivenInteractiveTransition 属性的 updateInteractiveTransition 方法实时更新百分比
4.最后实现UINavigationControllerDelegate的一个代理方法
- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController NS_AVAILABLE_IOS(7_0){
// 这里要判断 是pop返回 还是手势返回
return self.manager.isInteractive?self.manager:nil;
}
至此 手势驱动也完成了啊 是不是很简单呢 其实不是 这里面水很深的 有很多细节 尤其加入了手势驱动 pop动画尤其得注意了 具体的我在代码里面注释了 贴出demo地址demo地址
最后希望大家pi'p
网友评论