View Controller转场 - ZhiJianShuSheng/Read-And-Learn GitHub Wiki
UINavigationControllerDelegate中相关方法
- (id<UIViewControllerAnimatedTransitioning>)
navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController*)fromVC
toViewController:(UIViewController*)toVC
{
if (operation == UINavigationControllerOperationPush) {
//可以给每个转场创建新的animator对象,或者共用同一个animator
return self.animator;
}
return nil;
}
创建一个自定义的动画类
示例代码下载地址:https://github.com/objcio/issue5-view-controller-transitions
//实现这个协议
@interface Animator : NSObject <UIViewControllerAnimatedTransitioning>
@end
//动画持续时间
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.25;
}
//动画执行效果
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
[[transitionContext containerView] addSubview:toViewController.view];
toViewController.view.alpha = 0;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
fromViewController.view.transform = CGAffineTransformMakeScale(0.1, 0.1);
toViewController.view.alpha = 1;
} completion:^(BOOL finished) {
fromViewController.view.transform = CGAffineTransformIdentity;
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
//实现交互式转场动画,只需要覆盖另一个UINavigationControllerDelegate的方法
- (id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController*)navigationController
interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController
{
//返回的是UIPercentDrivenInteractionTransition类的一个实例
return self.interactionController;
}
//创建一个拖动手势Pan Rcognizer
if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) {
//当用户从屏幕右半部分开始触摸时,把下次动画效果设置为交互式
if (location.x > CGRectGetMidX(view.bounds)) {
navigationControllerDelegate.interactionController = [[UIPercentDrivenInteractiveTransition alloc] init];
[self performSegueWithIdentifier:PushSegueIdentifier sender:self];
}
} else if (panGestureRecognizer.state == UIGestureRecognizerStateChanged) {
//根据用户手指拖动的距离计算一个百分比,切换的动画效果也跟这个百分比走。
CGFloat d = (translation.x / CGRectGetWidth(view.bounds)) * -1;
[interactionController updateInteractiveTransition:d];
} else if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) {
//根据用户手势的停止状态来判断该操作是结束还是取消
if ([panGestureRecognizer velocityInView:view].x < 0) {
[interactionController finishInteractiveTransition];
} else {
[interactionController cancelInteractiveTransition];
}
navigationControllerDelegate.interactionController = nil;
}
用GPUImage做转场动画
示例代码地址:https://github.com/FangYiXiong/ViewControllerTransitionsDemo/tree/master/issue5-demo2%EF%BC%88GPUImage%EF%BC%89 实现的效果是两个view controller像素化,然后相互消融在一起。 先创建一个自定义类,实现UIViewControllerAnimatedTransitioning 和 UIViewControllerInteractiveTransitioning两个协议。将图片一次性加载到GPU中。直接用OpenGL画图使用GPUImage封装好的接口。
@interface GPUImageAnimator : NSObject
<UIViewControllerAnimatedTransitioning,
UIViewControllerInteractiveTransitioning>
@property (nonatomic) BOOL interactive;
@property (nonatomic) CGFloat progress;
- (void)finishInteractiveTransition;
- (void)cancelInteractiveTransition;
@end
创建滤镜链filter chain也很直观。GPUImage没有提供动画效果,可以使用CADisplayLink完成渲染一帧就更新下一滤镜的动态滤镜效果。
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(frame:)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
//在frame方法中,可以根据时间来更新动画,相应的更新滤镜:
- (void)frame:(CADisplayLink*)link
{
self.progress = MAX(0, MIN((link.timestamp - self.startTime) / duration, 1));
self.blend.mix = self.progress;
self.sourcePixellateFilter.fractionalWidthOfAPixel = self.progress *0.1;
self.targetPixellateFilter.fractionalWidthOfAPixel = (1- self.progress)*0.1;
[self triggerRenderOfNextFrame];
}
GPUImage开源库地址:https://github.com/BradLarson/GPUImage