如何仅让SwRevealController的单个菜单在横屏模式下显示?
解决SwRevealViewController侧滑菜单中特定页面横屏的问题
这个需求其实挺常见的,我之前也帮人处理过类似场景,咱们一步步来实现:
1. 先确保App层面支持横屏方向
首先得让你的App允许横屏,否则后续设置都没用。根据iOS版本,在AppDelegate或SceneDelegate里修改支持的方向:
// AppDelegate.swift(iOS 12及以下) func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { // 支持除倒转外的所有方向,后续由子控制器做限制 return .allButUpsideDown }
如果是iOS 13+用SceneDelegate:
// SceneDelegate.swift func windowScene(_ windowScene: UIWindowScene, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return .allButUpsideDown }
2. 给竖屏页面创建基类
为了避免重复代码,给Home、Profile这类需要竖屏的页面创建一个基类,让它们统一继承:
class PortraitBaseViewController: UIViewController { override var supportedInterfaceOrientations: UIInterfaceOrientationMask { // 仅允许竖屏 return .portrait } override var shouldAutorotate: Bool { // 禁止自动旋转 return false } }
然后修改你的竖屏页面:
class HomeViewController: PortraitBaseViewController { // 你的页面逻辑... } class ProfileViewController: PortraitBaseViewController { // 你的页面逻辑... }
3. 单独设置Parameters页面的横屏权限
让ParametersViewController自己声明支持横屏:
class ParametersViewController: UIViewController { override var supportedInterfaceOrientations: UIInterfaceOrientationMask { // 允许横屏(可根据需求选landscapeLeft/Right或allLandscape) return .landscape } override var shouldAutorotate: Bool { // 允许自动旋转 return true } }
4. 让SwRevealViewController尊重子控制器的旋转设置
SwRevealViewController作为容器控制器,默认会自行处理旋转逻辑,所以我们需要扩展它,让它优先遵循当前前台控制器的旋转规则:
extension SwRevealViewController { override open var supportedInterfaceOrientations: UIInterfaceOrientationMask { // 优先使用前台控制器的设置 if let frontVC = self.frontViewController { return frontVC.supportedInterfaceOrientations } return super.supportedInterfaceOrientations } override open var shouldAutorotate: Bool { if let frontVC = self.frontViewController { return frontVC.shouldAutorotate } return super.shouldAutorotate } }
5. 跳转时强制触发横屏(可选但推荐)
为了确保用户点击Parameters菜单时页面直接切换到横屏,在菜单的点击事件里添加强制旋转代码:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { var targetVC: UIViewController! switch indexPath.row { case 0: targetVC = HomeViewController() case 1: targetVC = ProfileViewController() case 2: targetVC = ParametersViewController() // 强制旋转到横屏 if let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) { let desiredOrientation = UIInterfaceOrientation.landscapeLeft UIDevice.current.setValue(desiredOrientation.rawValue, forKey: "orientation") UIViewController.attemptRotationToDeviceOrientation() } default: return } // 用自定义导航控制器包裹(如果需要导航栏) let navVC = CustomNavigationController(rootViewController: targetVC) revealViewController().pushFrontViewController(navVC, animated: true) tableView.deselectRow(at: indexPath, animated: true) }
6. 处理导航控制器的旋转传递(如果用了导航栏)
如果你用UINavigationController包裹子页面,需要让导航控制器把旋转权限传递给顶层子控制器,所以创建自定义导航控制器:
class CustomNavigationController: UINavigationController { override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return topViewController?.supportedInterfaceOrientations ?? .portrait } override var shouldAutorotate: Bool { return topViewController?.shouldAutorotate ?? false } }
这样一套操作下来,就能实现只有Parameters页面横屏、其他页面保持竖屏的效果了。测试时注意,模拟器可通过Cmd+Left/Right手动切换方向,真机直接旋转设备即可。
内容的提问来源于stack exchange,提问作者Nicat Gülüyev
相关产品推荐
相关产品推荐

