使用系统的方案
创建BaseNavgationViewController 继承父类UINavigationController
- (void)viewDidLoad {
[super viewDidLoad];
// 屏幕边缘滑动(只能在屏幕的边缘才能触发该手势,不能在屏幕的任意一点触发该手势)
UIScreenEdgePanGestureRecognizer *edgePanGestureRecognizer = (UIScreenEdgePanGestureRecognizer *)self.interactivePopGestureRecognizer;
// 滑动手势(禁用系统自带的屏幕边缘滑动手势,使用自定义的滑动手势目的就是达到触摸屏幕上的任意一点向右滑动都能实现返回的效果)
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:edgePanGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
panGestureRecognizer.delegate = self;
[self.view addGestureRecognizer:panGestureRecognizer];
// 禁用系统的屏幕边缘滑动手势
edgePanGestureRecognizer.enabled = NO;
}
// 是否允许触发手势,如果是根视图控制器则不需要
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return self.childViewControllers.count > 1;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
// 统一设置返回按钮
NSInteger count = self.childViewControllers.count;
if (count > 0) {
// viewController.hidesBottomBarWhenPushed = YES;
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"🔙" style:UIBarButtonItemStylePlain target:self action:@selector(back)];}
[super pushViewController:viewController animated:animated];
}
- (void)back {
[self popViewControllerAnimated:YES];
}
自定义动画和交互
创建BaseViewController 继承 UIViewController,去实现导航控制器的代理
- (nullable id #UIViewControllerInteractiveTransitioning#)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id) animationController NS_AVAILABLE_IOS(7_0);
返回一个实现交互过渡协议的对象。
- (nullable id #UIViewControllerAnimatedTransitioning#)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
返回一个实现动画过渡协议对象
具体代码实现
- (id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
if(operation == UINavigationControllerOperationPop) // 若operation是pop,就返回我们自定义的转场动画对象
{
PopAnimation *pop = [[PopAnimation alloc] init];
pop.popType = PopAnimationTypeFollow;
return pop;}
return nil;
}
- (id)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id)animationController
{
if([animationController isKindOfClass:[PopAnimation class]])
{
return _interactiveTransition;}
return nil;
}
PopAnimation实现动画交互的代码
PopAnimation要实现UIViewControllerAnimatedTransitioning 这个协议。
具体代码
// 返回动画执行的时间- (NSTimeInterval)transitionDuration:(id)transitionContext
{
return 1;
}
- (void)animateTransition:(id)transitionContext
{
// 来自哪个VC
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
// 到哪个VC
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
//设置fromvc的阴影
UIViewController *vc = fromVC;
// 阴影颜色
vc.view.layer.shadowColor = [UIColor blackColor].CGColor;
// 偏移量
vc.view.layer.shadowOffset = CGSizeMake(-10,0);
// 半径
vc.view.layer.shadowRadius = 5;
// 透明度
vc.view.layer.shadowOpacity = 0.3;
// 转场动画是两个控制器视图的动画,需要一个containerView作为“舞台”
UIView *containerView = [transitionContext containerView];
[containerView insertSubview:toVC.view belowSubview:fromVC.view];
// 获取动画执行时间(实现的协议方法)
NSTimeInterval duration = [self transitionDuration:transitionContext];
// 动画类型
switch (_popType) {
case PopAnimationTypeDefault:
{
// 执行动画,让fromVC的view移动到屏幕最右侧
[UIView animateWithDuration:duration animations:^{
fromVC.view.transform = CGAffineTransformMakeTranslation(ScreenW,0);} completion:^(BOOL finished) {
fromVC.view.transform = CGAffineTransformIdentity;
// 当动画执行完时,这个方法必须要调用,否则系统会认为你的其余操作都在动画执行过程中
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];}];}
break;
case PopAnimationTypeFollow:
{
toVC.view.transform = CGAffineTransformMakeTranslation(-ScreenW, 0);
[UIView animateWithDuration:duration animations:^{
fromVC.view.transform = CGAffineTransformMakeTranslation(ScreenW,0);
toVC.view.transform = CGAffineTransformMakeTranslation(0, 0);} completion:^(BOOL finished) {
fromVC.view.transform = CGAffineTransformIdentity;
toVC.view.transform = CGAffineTransformIdentity;
// 当动画执行完时,这个方法必须要调用,否则系统会认为你的其余操作都在动画执行过程中
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];}];}
break;
default:
break;}
}