如何在iPhone X横屏时强制UITabBar使用紧凑样式?
iPhone X横屏UITabBar图标布局异常的解决方案
我之前在做自定义UITabBar适配的时候,也碰到过和你一模一样的问题——毕竟UITabBarController内部有一套系统默认的适配逻辑,单独使用UITabBar时这套逻辑不会自动触发。结合你已经做的安全区域设置和容器视图调整,给你几个亲测有效的解决方案:
1. 监听设备旋转,手动调整Item布局
通过监听设备旋转事件,在横屏时针对iPhone X系列设备单独调整tabBar的item间距、图标内边距等属性,让布局恢复正常:
override func viewDidLoad() { super.viewDidLoad() // 添加旋转监听通知 NotificationCenter.default.addObserver(self, selector: #selector(handleScreenRotation), name: UIDevice.orientationDidChangeNotification, object: nil) } @objc private func handleScreenRotation() { guard let tabBar = self.customTabBar else { return } let isLandscape = UIDevice.current.orientation.isLandscape let isIPhoneXSeries = UIDevice.current.userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height >= 2436 if isLandscape && isIPhoneXSeries { // 横屏适配:调整item间距和图标内边距 tabBar.itemSpacing = 18 // 可根据实际需求修改 tabBar.items?.forEach { item in item.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) } } else { // 恢复竖屏/非X设备的默认布局 tabBar.itemSpacing = 0 tabBar.items?.forEach { item in item.imageInsets = .zero } } } deinit { // 记得移除通知,避免内存泄漏 NotificationCenter.default.removeObserver(self) }
2. 自定义UITabBar子类,重写布局逻辑
通过自定义UITabBar子类,在layoutSubviews方法中模拟UITabBarController的横屏布局逻辑,强制让item均匀分布在安全区域内:
class AdaptiveTabBar: UITabBar { override func layoutSubviews() { super.layoutSubviews() let isLandscape = UIDevice.current.orientation.isLandscape let isIPhoneXSeries = UIDevice.current.userInterfaceIdiom == .phone && UIScreen.main.nativeBounds.height >= 2436 guard isLandscape && isIPhoneXSeries else { // 非目标场景,使用系统默认布局 super.layoutSubviews() return } // 获取横屏时的安全区域左右留白(对应刘海和底部指示条区域) let safeInset = self.safeAreaInsets let availableWidth = self.bounds.width - safeInset.left - safeInset.right let itemCount = self.items?.count ?? 0 guard itemCount > 0 else { return } // 计算每个item的宽度 let itemWidth = availableWidth / CGFloat(itemCount) // 遍历调整每个tabBarItem的视图布局 self.subviews.forEach { subview in // 识别UITabBarButton(系统内部的item视图类) if NSStringFromClass(subview.classForCoder) == "UITabBarButton" { let index = subview.tag // 系统默认会给tabBarButton设置对应item的索引tag subview.frame = CGRect( x: safeInset.left + itemWidth * CGFloat(index), y: subview.frame.origin.y, width: itemWidth, height: subview.frame.height ) } } } }
使用时直接把你的UITabBar替换成这个自定义类即可,它会自动处理横屏时的布局适配。
3. 优先考虑使用UITabBarController(如果场景允许)
如果你的业务场景没有强需求必须单独使用UITabBar,最省心的方式还是直接用UITabBarController来管理标签栏——系统已经帮我们处理了所有设备(包括iPhone X横屏)的适配逻辑,不需要额外写适配代码。
额外注意点
- 确保你的UITabBar容器视图已经正确绑定了
safeAreaLayoutGuide的约束,避免出现错位问题; - 测试时覆盖iPhone X系列的所有机型(X、XS、XR、11及后续刘海屏机型),因为不同机型的安全区域Insets可能略有差异。
内容的提问来源于stack exchange,提问作者Nathan Barreto
相关产品推荐
相关产品推荐

