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

如何不使用Storyboards和CocoaPods实现类KYDrawerController的侧滑菜单?

嘿,我来帮你捋捋这个问题~

方案一:纯代码手动实现侧滑菜单

如果你想自己从零搭建,核心是做一个容器ViewController来管理主界面和侧滑菜单,以下是关键步骤:

  • 第一步:搭建基础容器结构
    创建一个容器VC,把主VC和菜单VC都作为子VC添加进去。初始状态下,菜单VC藏在屏幕左侧外面,主VC占满整个屏幕。
    示例代码:

    class DrawerContainerVC: UIViewController {
        // 自定义菜单宽度,可根据需求调整
        let menuWidth: CGFloat = 280
        private var menuVC: MenuViewController!
        private var mainVC: UIViewController!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            setupMainViewController()
            setupMenuViewController()
        }
        
        private func setupMainViewController() {
            // 替换成你的初始主视图控制器
            mainVC = YourInitialMainVC()
            addChild(mainVC)
            mainVC.view.frame = view.bounds
            view.addSubview(mainVC.view)
            mainVC.didMove(toParent: self)
        }
        
        private func setupMenuViewController() {
            // 替换成你的菜单视图控制器
            menuVC = YourMenuVC()
            addChild(menuVC)
            // 初始位置:完全藏在左侧
            menuVC.view.frame = CGRect(x: -menuWidth, y: 0, width: menuWidth, height: view.bounds.height)
            view.addSubview(menuVC.view)
            menuVC.didMove(toParent: self)
        }
    }
    
  • 第二步:添加侧滑手势交互
    给主VC的视图添加拖动手势,根据手势偏移量调整菜单的位置,同时给主VC加一点缩放动画增强视觉效果:

    // 在DrawerContainerVC的viewDidLoad里添加手势
    override func viewDidLoad() {
        super.viewDidLoad()
        setupMainViewController()
        setupMenuViewController()
        addPanGesture()
    }
    
    private func addPanGesture() {
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
        mainVC.view.addGestureRecognizer(panGesture)
    }
    
    @objc private func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
        let translation = gesture.translation(in: view)
        var currentMenuX = menuVC.view.frame.origin.x
        
        switch gesture.state {
        case .changed:
            // 限制菜单只能在[-menuWidth, 0]范围内移动
            currentMenuX = max(-menuWidth, min(currentMenuX + translation.x, 0))
            menuVC.view.frame.origin.x = currentMenuX
            // 主VC随菜单展开比例缩放,增强层次感
            let scaleRatio = 1 - (abs(currentMenuX)/menuWidth)*0.15
            mainVC.view.transform = CGAffineTransform(scaleX: scaleRatio, y: scaleRatio)
            // 重置手势偏移,避免连续拖动时的累积问题
            gesture.setTranslation(.zero, in: view)
        case .ended, .cancelled:
            // 手势结束时,根据菜单当前位置判断是完全展开还是收起
            let shouldOpen = currentMenuX > -menuWidth/2
            UIView.animate(withDuration: 0.3) {
                self.menuVC.view.frame.origin.x = shouldOpen ? 0 : -self.menuWidth
                self.mainVC.view.transform = shouldOpen ? CGAffineTransform(scaleX: 0.85, y: 0.85) : .identity
            }
            // 切换点击手势的启用状态
            self.mainVC.view.gestureRecognizers?.first(where: { $0 is UITapGestureRecognizer })?.isEnabled = shouldOpen
        default:
            break
        }
    }
    
  • 第三步:添加菜单收起逻辑
    可以给主VC添加点击手势,当菜单展开时,点击主VC区域自动收起菜单:

    // 在DrawerContainerVC的viewDidLoad里添加
    override func viewDidLoad() {
        super.viewDidLoad()
        setupMainViewController()
        setupMenuViewController()
        addPanGesture()
        addTapToCloseGesture()
    }
    
    private func addTapToCloseGesture() {
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(closeMenu))
        mainVC.view.addGestureRecognizer(tapGesture)
        // 初始时禁用点击,只有菜单展开后才启用
        tapGesture.isEnabled = false
    }
    
    @objc private func closeMenu() {
        UIView.animate(withDuration: 0.3) {
            self.menuVC.view.frame.origin.x = -self.menuWidth
            self.mainVC.view.transform = .identity
        } completion: { _ in
            // 收起后禁用点击手势
            self.mainVC.view.gestureRecognizers?.first(where: { $0 is UITapGestureRecognizer })?.isEnabled = false
        }
    }
    
方案二:直接使用KYDrawerController的评估

如果你纠结要不要用这个库,我给你分析下:

  • 为什么值得用?
    • 成熟省心:这个库已经经过大量项目验证,像屏幕旋转、手势冲突、边缘触发这些细节都处理好了,自己实现要花不少时间踩坑。
    • 功能完善:除了基础侧滑,它还支持自定义抽屉宽度、手势灵敏度、甚至多方向抽屉,这些功能自己写的话得额外花精力。
  • 解决你担心的Swift版本问题
    不用CocoaPods就行!直接把KYDrawerController的源码文件拖进你的项目里,这样Swift更新后,你可以自己修改源码适配新版本——它的核心逻辑不算复杂,适配成本很低,完全不用等作者更新。
最终建议
  • 如果你的项目时间紧张,或者不想在自定义容器VC上花太多精力,直接集成KYDrawerController源码是更高效的选择;
  • 如果是想学习自定义容器ViewController的实现逻辑,或者需要高度定制的效果,那自己手动实现一遍会收获很多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:17:24