Swift 4中如何无需按钮实现侧边菜单隐藏?
解决Swift 4侧边菜单点击外部自动隐藏的问题
嘿,针对你遇到的侧边菜单需要点击外部区域自动隐藏的需求,这里有两种实用的解决方案,完全适配你的现有代码结构:
方法一:添加全屏点击手势(推荐)
在你的ContainerVC的viewDidLoad中添加一个全屏点击手势,触发时判断侧边菜单状态,同时避免拦截菜单内部的点击事件:
class ContainerVC: UIViewController { @IBOutlet weak var constraint: NSLayoutConstraint! var sideMenuOpen = false override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(toggleSideMenu), name: NSNotification.Name("ToggleSideMenu"), object: nil) // 添加全屏点击手势 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapOutside)) tapGesture.cancelsTouchesInView = false // 允许底层控件接收触摸事件 self.view.addGestureRecognizer(tapGesture) } @objc func handleTapOutside(_ gesture: UITapGestureRecognizer) { guard sideMenuOpen else { return } let tapPoint = gesture.location(in: self.view) // 替换成你实际的侧边菜单视图(比如从子控制器获取) if let sideMenuView = self.childViewControllers.first(where: { $0 is SideMenuVC })?.view { if !sideMenuView.frame.contains(tapPoint) { toggleSideMenu() } } else { // 找不到菜单视图时直接关闭(可选逻辑) toggleSideMenu() } } @objc func toggleSideMenu() { sideMenuOpen = !sideMenuOpen // 根据你的菜单方向调整约束值,这里以左侧菜单为例 constraint.constant = sideMenuOpen ? 0 : -280 // 280替换成你的菜单实际宽度 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } } }
方法二:重写hitTest拦截触摸事件
通过重写容器控制器的hitTest方法,直接判断触摸点位置,触发关闭逻辑:
class ContainerVC: UIViewController { @IBOutlet weak var constraint: NSLayoutConstraint! var sideMenuOpen = false override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(toggleSideMenu), name: NSNotification.Name("ToggleSideMenu"), object: nil) } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let touchedView = super.hitTest(point, with: event) guard sideMenuOpen else { return touchedView } // 获取侧边菜单视图 if let sideMenuView = self.childViewControllers.first(where: { $0 is SideMenuVC })?.view { if !sideMenuView.frame.contains(point) { toggleSideMenu() return nil // 让底层视图处理本次触摸 } } return touchedView } @objc func toggleSideMenu() { sideMenuOpen = !sideMenuOpen constraint.constant = sideMenuOpen ? 0 : -280 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } } }
关键注意点
- 确保能正确获取侧边菜单视图:如果是通过添加子控制器的方式实现侧边菜单,用
childViewControllers查找对应的SideMenuVC再取view即可。 - 调整约束数值时,要和你当前菜单的打开/关闭逻辑匹配,右侧菜单可以修改trailing约束。
- 手势方法中
cancelsTouchesInView = false必须设置,否则会拦截其他按钮的点击事件。
内容的提问来源于stack exchange,提问作者chen
相关产品推荐
相关产品推荐

