You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS自定义unwind segue动画:实现汉堡菜单返回左滑退出

解决iOS汉堡菜单返回时左侧滑出动画的方案

我明白你现在的痛点——好不容易实现了汉堡菜单从左侧滑入的效果,但系统默认的返回动画还是向右滑出,和菜单的进入逻辑完全不匹配,而且自动生成的返回按钮没法直接通过segue修改动画。这里有几个实用的解决方向,你可以根据自己的场景选择:

方向1:自定义返回按钮,完全掌控动画逻辑

系统自动生成的返回按钮绑定的是默认的pop行为,很难直接修改它的动画。最简单的办法就是替换掉这个按钮,自己实现点击后的动画和页面跳转:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 替换系统返回按钮为自定义按钮
    let customBackButton = UIBarButtonItem(
        image: UIImage(named: "your-back-icon"), // 用你自己的返回图标
        style: .plain,
        target: self,
        action: #selector(onBackButtonTapped)
    )
    navigationItem.leftBarButtonItem = customBackButton
    // 去掉系统自带的返回文字
    navigationItem.backButtonTitle = ""
}

@objc private func onBackButtonTapped() {
    // 执行左侧滑出的自定义动画
    UIView.animate(withDuration: 0.3, animations: {
        self.view.frame.origin.x = -UIScreen.main.bounds.width
    }) { [weak self] finished in
        guard finished else { return }
        // 动画结束后,无动画地pop回原页面
        self?.navigationController?.popViewController(animated: false)
    }
}

这种方式的好处是逻辑简单,不需要依赖系统的导航动画,完全由你自己控制。

方向2:自定义导航控制器的pop动画

如果希望整个导航栈的返回动画都统一为左侧滑出,或者不想替换返回按钮,可以通过自定义导航控制器的代理来实现全局动画控制:

首先创建一个自定义的动画控制器类,实现UIViewControllerAnimatedTransitioning协议:

class LeftSlideOutTransition: NSObject, UIViewControllerAnimatedTransitioning {
    // 动画时长
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.3
    }
    
    // 具体动画逻辑
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromVC = transitionContext.viewController(forKey: .from),
              let toVC = transitionContext.viewController(forKey: .to) else {
            transitionContext.completeTransition(false)
            return
        }
        
        let container = transitionContext.containerView
        container.addSubview(toVC.view)
        
        // 初始状态:原页面在左侧,当前菜单页面在屏幕内
        toVC.view.frame.origin.x = -container.bounds.width
        fromVC.view.frame.origin.x = 0
        
        // 执行滑出动画:菜单页面滑到左侧,原页面回到屏幕内
        UIView.animate(withDuration: transitionDuration(using: transitionContext)) {
            fromVC.view.frame.origin.x = -container.bounds.width
            toVC.view.frame.origin.x = 0
        } { finished in
            transitionContext.completeTransition(finished && !transitionContext.transitionWasCancelled)
        }
    }
}

然后创建自定义导航控制器,设置代理并返回动画控制器:

class CustomNavController: UINavigationController, UINavigationControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }
    
    func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        // 只有pop操作时使用自定义左侧滑出动画
        if operation == .pop {
            return LeftSlideOutTransition()
        }
        // 推入页面时可以保留你之前实现的左侧滑入动画
        return nil
    }
}

最后记得把Storyboard里的导航控制器的类改成CustomNavController,这样所有的pop操作都会使用你自定义的左侧滑出动画了。

方向3:修复Unwind Segue的动画(如果坚持用Unwind)

如果你之前尝试用Unwind Segue但没成功,可能是没正确绑定动画控制器。可以试试:

  1. 在主页面(汉堡菜单的父页面)定义一个Unwind动作:
@IBAction func unwindToMain(_ sender: UIStoryboardSegue) {}
  1. 在Storyboard里,从MenuViewController的导航栏返回按钮拖线到页面底部的"Exit"图标,选择刚才定义的unwindToMain动作,给这个segue设置一个标识符(比如"unwindToMainSegue")。
  2. 在MenuViewController里实现UIViewControllerTransitioningDelegate,返回自定义的返回动画控制器:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "unwindToMainSegue" {
        segue.destination.transitioningDelegate = self
    }
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return LeftSlideOutTransition() // 用刚才定义的动画类
}

这种方式相对复杂一些,适合已经大量使用Unwind Segue的场景。

内容的提问来源于stack exchange,提问作者NullHypothesis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:42:36