如何实现导航视图控制器滑动时的即时转场(避免转场取消)
嘿,我完全get你的需求——你想保留导航控制器的滑动返回和顶部返回按钮功能,但烦透了用户滑到一半又取消、停在当前页面的情况,而且不想粗暴地禁用滑动返回对吧?这有两个优雅的实现方案,能让转场一旦触发就直接完成:
方案一:强制完成交互式滑动转场(保留系统滑动动画)
这个方案会保留系统原生的滑动返回动画,但只要用户开始滑动,就强制转场完成,不允许中途取消。核心是通过UINavigationControllerDelegate和UIPercentDrivenInteractiveTransition来控制转场进度:
class CustomNavigationController: UINavigationController, UINavigationControllerDelegate { private var interactiveTransition: UIPercentDrivenInteractiveTransition? override func viewDidLoad() { super.viewDidLoad() delegate = self } // 处理交互式转场的控制器 func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { // 一旦滑动转场被触发,直接强制完成 interactiveTransition?.finishInteractiveTransition() return interactiveTransition } // 配置转场动画控制器 func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { // 只有返回操作时才初始化交互式转场 if operation == .pop { interactiveTransition = UIPercentDrivenInteractiveTransition() interactiveTransition?.completionSpeed = 1.0 // 确保动画全速完成 } else { interactiveTransition = nil } return nil // 使用系统默认的返回动画 } }
说明:当用户触发滑动返回手势时,我们直接调用finishInteractiveTransition(),让系统立刻完成整个转场动画,不管用户有没有继续滑动,这样就不会出现中途停住的情况。
方案二:拦截滑动手势,直接触发普通返回
如果你不需要保留滑动过程中的交互感,只想让滑动手势直接触发返回操作,可以拦截系统的滑动返回手势,一旦检测到手势开始,就直接调用普通的popViewController:
class YourContentViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 获取系统自带的滑动返回手势 guard let popGesture = navigationController?.interactivePopGestureRecognizer else { return } popGesture.delegate = self } } extension YourContentViewController: UIGestureRecognizerDelegate { func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { // 确保当前不是根控制器,避免崩溃 guard navigationController?.viewControllers.count ?? 0 > 1 else { return false } // 直接触发返回操作 navigationController?.popViewController(animated: true) return false // 阻止系统的交互式手势继续执行 } }
说明:这个方案相当于把滑动手势变成了一个“触发式”的按钮,用户只要开始滑动,就立刻执行普通的返回动画,完全跳过系统的交互式转场逻辑,自然也就不存在中途取消的问题。
你可以根据自己的需求选择:如果想保留滑动的动画过程但不允许取消,方案一更合适;如果追求简单直接,方案二上手更快。
内容的提问来源于stack exchange,提问作者Adam S.
相关产品推荐
相关产品推荐

