自定義轉(zhuǎn)場動畫主要有以下步驟
- 自定義導航欄
- 自定義交互動畫
- 通過UIPercentDrivenInteractiveTransition協(xié)議實現(xiàn)交互
自定義導航欄
自定義導航欄需要遵守<UINavigationControllerDelegate>協(xié)議采幌,該協(xié)議主要有兩個協(xié)議方法:
// 該方法返回導航跳轉(zhuǎn)時的動畫休傍,如果返回nil,則是系統(tǒng)默認的跳轉(zhuǎn)動畫磨取,并且通過operation來判斷當前執(zhí)行push還是pop
-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
return nil;
}
// 該方法返回自定義交互動畫柴墩,只有實現(xiàn)該協(xié)議,才能在跳轉(zhuǎn)時實現(xiàn)與用戶交互
-(id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
{
return nil;
}
自定義跳轉(zhuǎn)動畫
自定義跳轉(zhuǎn)動畫需要遵守<UIViewControllerAnimatedTransitioning>協(xié)議逢净,該協(xié)議主要實現(xiàn)下面的方法:
// 該方法返回動畫執(zhí)行的時間歼指,transitionContext由系統(tǒng)獲取
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.3;
}
// 通過該協(xié)議,獲取跳轉(zhuǎn)的兩個VC
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
[self animateTransition:transitionContext fromVC:fromVC toVC:toVC fromView:fromVC.view toView:toVC.view];
}
// 這是模仿系統(tǒng)導航跳轉(zhuǎn)的例子
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView{
[[transitionContext containerView] addSubview:toView];
if (_isPush) {
[[transitionContext containerView] bringSubviewToFront:toView];
toView.transform = CGAffineTransformMakeTranslation(-toView.bounds.size.width, 0);
}
else{
[[transitionContext containerView] bringSubviewToFront:fromView];
}
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
if (_isPush) {
toView.transform = CGAffineTransformIdentity;
}
else{
fromView.transform = CGAffineTransformMakeTranslation(-fromView.bounds.size.width, 0);
}
} completion:^(BOOL finished) {
transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
實現(xiàn)交互
自定義一個類,繼承自UIPercentDrivenInteractiveTransition挟阻,它遵守<UIViewControllerInteractiveTransitioning>協(xié)議,我們可以告訴它當前轉(zhuǎn)場動畫進行的百分比脱拼,它再來更新動畫的進度。轉(zhuǎn)場動畫進行的百分比可以通過手勢來計算
// 在view上加入pan手勢
UIPanGestureRecognizer *gesture = objc_getAssociatedObject(self.interactiveVC.view, (__bridge const void *)(kpanGestureKey));
if (gesture) {
[self.interactiveVC.view removeGestureRecognizer:gesture];
}
gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
[self.interactiveVC.view addGestureRecognizer:gesture];
objc_setAssociatedObject(self.interactiveVC.view, (__bridge const void *)(kpanGestureKey), gesture,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// 當pan手勢移動挪拟,通過移動的距離來計算當前跳轉(zhuǎn)動畫需要完成的百分比击你,當手勢結(jié)束時,判斷動畫完成的百分比丁侄。如果>50%,finishInteractiveTransition完成跳轉(zhuǎn)動畫石景;如果<50%拙吉,cancelInteractiveTransition取消動畫,返回原樣
case UIGestureRecognizerStateChanged:
CGFloat fraction = point.x / [[UIScreen mainScreen] bounds].size.width;
fraction = fminf(fmaxf(fraction, 0.0), 1.0);
self.shouldComplete = (fraction > 0.5);
[self updateInteractiveTransition:fraction];
break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
self.interactioning = NO;
if (!self.shouldComplete || pan.state == UIGestureRecognizerStateCancelled) {
[self cancelInteractiveTransition];
}
else {
[self finishInteractiveTransition];
}
break;