接上篇文章,相信大家实现简单的Push已经不再话下了把,那么上一篇是入门,这一篇将继续介绍如何实现手势返回。
我们需要实现最重要的交互过程的类:
UIPercentDrivenInteractiveTransition
这里面的方法相信大家已经知道,最重要的3个方法:
- (void)updateInteractiveTransition:(CGFloat)percentComplete;
- (void)cancelInteractiveTransition;
- (void)finishInteractiveTransition;
我们通过手势控制,然后通过手势去更新我们的交互过程,主要就是依靠以上方法去更新我们的交互过程。
首先,我们简单一点,先写一个Pop的动画,直接附上源码:
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.2;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
CGRect screenBounds = [[UIScreen mainScreen] bounds];
UIViewController * fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController * toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
CGRect initFrame = [transitionContext initialFrameForViewController:fromVC];
CGRect finalFrame = CGRectOffset(initFrame, screenBounds.size.width , 0);
UIView *containerView = [transitionContext containerView];
[containerView addSubview:toVC.view];
[containerView sendSubviewToBack:toVC.view];
NSTimeInterval duration = [self transitionDuration:transitionContext];
[UIView animateWithDuration:duration animations:^{
//fromVC.view.alpha = 0.0;
fromVC.view.transform = CGAffineTransformMakeScale(1.0, 0.0001);
} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
和Push进来的动画差不多,但是注意
UIView *containerView = [transitionContext containerView];
[containerView addSubview:toVC.view];
[containerView sendSubviewToBack:toVC.view];
这几句非常关键,我们在实现页面转换的时候,需要一个容器进行动画转场,而系统就替我们创建了一个转场的View,需要注意,如果不加上这句话,我们的转场动画会突然黑一下,因为我们的ToviewController.View没有添加在容器内,容器内空空如也,所以直接就是黑色,如果加了这个,等于我们有了个背景一样,就比较好流畅了。
Pop的动画实现了,我们怎么实现手势控制呢?
- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator
还记得这个吗,就是我们一开始transitioningDelegate
这个是负责交互控制,如果动画是交互的动画实现,那么这个就是控制动画的,注意上面的
UIPercentDrivenInteractiveTransition
也是遵循
UIViewControllerInteractiveTransitioning
所以我们完全可以实现一个负责交互控制的类。
- (void)prepareForController:(UIViewController *)controller
{
self.presentViewController = controller;
UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
[controller.view addGestureRecognizer:gesture];
}
-(CGFloat)completionSpeed
{
return 1 - self.percentComplete;
}
- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer {
CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview];
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:
// 1. Mark the interacting flag. Used when supplying it in delegate.
self.interacting = YES;
[self.presentViewController dismissViewControllerAnimated:YES completion:nil];
break;
case UIGestureRecognizerStateChanged: {
// 2. Calculate the percentage of guesture
NSLog(@"........%f",translation.y);
CGFloat fraction = translation.y / 400.0;
//Limit it between 0 and 1
fraction = fminf(fmaxf(fraction, 0.0), 1.0);
self.shouldComplete = (fraction > 0.5);
[self updateInteractiveTransition:fraction];
break;
}
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled: {
// 3. Gesture over. Check if the transition should happen or not
self.interacting = NO;
if (!self.shouldComplete || gestureRecognizer.state == UIGestureRecognizerStateCancelled) {
[self cancelInteractiveTransition];
} else {
[self finishInteractiveTransition];
}
break;
}
default:
break;
}
}
我们通过手势,去更新交互,取消交互或者完成交互,这样就完成了,我们从第一篇,讲如何push到一个页面,如何Pop,如何手势Pop。
还有一点需要注意,手势的更新,取消,只是让我们去控制Pop的动画。
如果你需要Demo,或者有疑问,请加入群组
478234972