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

无需容器ViewController与CocoaPods:在已有UIKit单页应用中集成侧边菜单的实现方案咨询

不用容器ViewController实现侧边菜单的方案

嘿,完全理解你不想动现有架构、不想引入第三方库的想法——毕竟项目代码量不小,重构容器VC的成本确实很高。这里给你一个纯原生、不用容器VC的实现思路,亲测可行:

核心思路

直接把侧边菜单ViewController的视图添加到主窗口(或导航控制器视图)上,通过修改视图位置配合UIKit动画实现滑入滑出,全程不用嵌套容器VC。

具体步骤

1. 准备侧边菜单VC

  • 在Storyboard里给你的侧边菜单VC设置一个唯一的Storyboard ID(比如SideMenuVC),方便后续初始化。
  • 在你的主ViewController里添加一个属性,用来持有侧边菜单VC的引用(避免被提前释放):
    private var sideMenuVC: SideMenuViewController?
    

2. 初始化并配置菜单视图

在你点击左上角BarButtonItem的触发方法里,先初始化菜单VC(只初始化一次):

@IBAction func toggleSideMenu(_ sender: UIBarButtonItem) {
    // 如果菜单还没初始化,先创建实例
    if sideMenuVC == nil {
        sideMenuVC = storyboard?.instantiateViewController(withIdentifier: "SideMenuVC")
        guard let menuView = sideMenuVC?.view else { return }
        
        // 配置菜单视图初始位置:左侧完全隐藏
        let menuWidth = UIScreen.main.bounds.width * 0.8 // 菜单宽度设为屏幕80%,可调整
        menuView.frame = CGRect(
            x: -menuWidth,
            y: 0,
            width: menuWidth,
            height: UIScreen.main.bounds.height
        )
        
        // 给菜单加阴影,提升视觉层次
        menuView.layer.shadowColor = UIColor.black.cgColor
        menuView.layer.shadowOpacity = 0.3
        menuView.layer.shadowOffset = CGSize(width: 2, height: 0)
        
        // 将菜单视图添加到主窗口(如果希望菜单在导航栏上方,用这个;如果要在导航栏下方,换成navigationController?.view.addSubview(menuView))
        UIApplication.shared.windows.first?.addSubview(menuView)
    }
    
    // 切换菜单显示/隐藏状态
    toggleMenuAnimation()
}

3. 实现滑入滑出动画

添加动画方法,修改菜单视图的x坐标来实现滑入:

private func toggleMenuAnimation() {
    guard let menuView = sideMenuVC?.view else { return }
    let menuWidth = menuView.bounds.width
    
    UIView.animate(withDuration: 0.3, curve: .easeInOut) {
        // 根据当前位置判断是显示还是隐藏
        if menuView.frame.origin.x < 0 {
            // 滑入:x坐标设为0
            menuView.frame.origin.x = 0
            // 给主视图添加点击遮罩,点击空白处关闭菜单
            self.addTapToCloseMenu()
        } else {
            // 滑出:x坐标设为负的菜单宽度
            menuView.frame.origin.x = -menuWidth
            // 移除点击遮罩
            self.removeTapToCloseMenu()
        }
    }
}

4. 添加点击空白关闭菜单的逻辑

实现点击遮罩关闭菜单的辅助方法:

private func addTapToCloseMenu() {
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(closeMenu))
    // 给主窗口加遮罩视图,或者直接给主VC的view加手势(注意要让手势能响应)
    let maskView = UIView(frame: UIScreen.main.bounds)
    maskView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
    maskView.tag = 999 // 标记遮罩视图,方便后续移除
    UIApplication.shared.windows.first?.addSubview(maskView)
    maskView.addGestureRecognizer(tapGesture)
}

private func removeTapToCloseMenu() {
    UIApplication.shared.windows.first?.viewWithTag(999)?.removeFromSuperview()
}

@objc private func closeMenu() {
    toggleMenuAnimation()
}

5. 内存管理注意事项

在主VC的deinit方法里,记得清理菜单视图和VC引用,避免内存泄漏:

deinit {
    sideMenuVC?.view.removeFromSuperview()
    sideMenuVC = nil
}

额外优化点

  • 如果你的项目用Auto Layout而不是frame,可以给菜单视图添加leading约束到父视图,初始值设为-menuWidth,动画时把约束的constant改成0,这样适配不同屏幕更灵活。
  • 如果侧边菜单需要处理导航跳转(比如跳转到设置页),可以通过获取根导航控制器来实现:
    let rootNav = UIApplication.shared.windows.first?.rootViewController as? UINavigationController
    rootNav?.pushViewController(settingVC, animated: true)
    

这样一来,你完全不用改动现有导航控制器的结构,也不用引入任何第三方库,就能实现侧边菜单的滑入滑出效果啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 08:58:15