iOS开发中,常见界面之间的跳转方式有:
- 1-改变window的根视图;
- 2-模态跳转(present/dismiss);
- 3-导航控制器的push(show)和pop.
但在实际开发中,以上三种界面跳转的方式无法满足我们的需求时,需要我们DIY,然后自定义模态跳转就起作用了.
下面通过写一个Demo来展示自定义模态跳转(Demo传送门在最后)
- 利用UIPageViewController实现卡片是分页滚动
- 自定义视图的模态跳转
1-present跳转核心代码
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
UIView *containerView = [transitionContext containerView];
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
CGRect initialFrame = self.originFrame;
CGRect finalFrame = [transitionContext finalFrameForViewController:toVC];
UIImageView *snapshot = [AnimationHelper getImage:toVC.view];
snapshot.frame = initialFrame;
snapshot.layer.cornerRadius = 25;
snapshot.layer.masksToBounds = YES;
[containerView addSubview:toVC.view];
[containerView addSubview:snapshot];
toVC.view.hidden = YES;
[AnimationHelper perspectiveTransformForContainerView:containerView];
snapshot.layer.transform = [AnimationHelper yRotation:M_PI_2];
CGFloat duration = [self transitionDuration:transitionContext];
[UIView animateKeyframesWithDuration:duration delay:0 options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{
snapshot.layer.transform = [AnimationHelper yRotation:M_PI_2];
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.33 animations:^{
fromVC.view.layer.transform = [AnimationHelper yRotation:-M_PI_2];
}];
[UIView addKeyframeWithRelativeStartTime:0.33 relativeDuration:0.33 animations:^{
snapshot.layer.transform = [AnimationHelper yRotation:0.0];
}];
[UIView addKeyframeWithRelativeStartTime:0.66 relativeDuration:0.33 animations:^{
snapshot.frame = finalFrame;
}];
} completion:^(BOOL finished) {
toVC.view.hidden = NO;
fromVC.view.layer.transform = [AnimationHelper yRotation:0.0];
[snapshot removeFromSuperview];
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
2-dismiss跳转核心代码
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
UIView *containerView = [transitionContext containerView];
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
CGRect finialFrame = self.destinationFrame;
UIImageView *snapshot = [AnimationHelper getImage:fromVC.view];
snapshot.layer.cornerRadius = 25;
snapshot.layer.masksToBounds = YES;
[containerView addSubview:toVC.view];
[containerView addSubview:snapshot];
fromVC.view.hidden = YES;
[AnimationHelper perspectiveTransformForContainerView:containerView];
toVC.view.layer.transform = [AnimationHelper yRotation:-M_PI_2];
CGFloat duration = [self transitionDuration:transitionContext];
[UIView animateKeyframesWithDuration:duration delay:0 options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.33 animations:^{
snapshot.frame = finialFrame;
}];
[UIView addKeyframeWithRelativeStartTime:0.33 relativeDuration:0.33 animations:^{
snapshot.layer.transform = [AnimationHelper yRotation:M_PI_2];
}];
[UIView addKeyframeWithRelativeStartTime:0.66 relativeDuration:0.33 animations:^{
toVC.view.layer.transform = [AnimationHelper yRotation:0.0];
}];
} completion:^(BOOL finished) {
fromVC.view.hidden = false;
[snapshot removeFromSuperview];
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
3-跳需要模态跳转的控制器中接受代理
#pragma mark --------------------关键代码
revealVC.transitioningDelegate = self;
[self.swipeInteractionController wireToViewController:revealVC];
#pragma mark --------------------关键代码
[self showViewController:revealVC sender:nil];
4-实现UIViewControllerTransitioningDelegate代理方法
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
self.flipPresentAnimationController.originFrame = self.cardView.frame;
return self.flipPresentAnimationController;
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
self.flipDismissAnimationController.destinationFrame = self.cardView.frame;
return self.flipDismissAnimationController;
}
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator {
return self.swipeInteractionController.interactionInProgress ? self.swipeInteractionController : nil;
}
Demo的传送门: