ios leftBarButtonItem无法设置宽度

本文介绍了一个常见的UIButton初始化错误,即直接使用label进行初始化,这会导致无法正确设置按钮大小。正确的做法是首先初始化UIButton的帧,然后使用UIBarButtonItem进行自定义视图的初始化,最后设置为navigationItem的左侧按钮。

 

错误:直接将一个label给initWithCustomView。这样将无法设置大小

 

先初始化UIButton的initWithFrame

UIBarButtonItem再initWithCustomView

最后self.navigationItem.leftBarButtonItem = leftButton; 

<think>我们正在构建一个分栏视图控制器(UISplitViewController),并希望设置主视图和详情视图的宽度各占一半,同时还要兼容低版本的iOS系统。 在UISplitViewController中,我们可以通过设置`preferredPrimaryColumnWidthFraction`和`maximumPrimaryColumnWidth`来控制主视图的宽度。 但是,如果我们希望主视图和详情视图各占一半,需要注意以下几点: 1. `preferredPrimaryColumnWidthFraction`属性用于设置主视图宽度占整个分栏视图宽度的比例(0.0到1.0之间)。如果我们希望各占一半,可以设置为0.5。 2. `maximumPrimaryColumnWidth`属性用于设置主视图的最大宽度,我们可以设置为一个较大的值,或者通过计算屏幕宽度的一半来设置。 3. 对于低版本(iOS 8.0以上,因为UISplitViewController在iPad上从iOS 8.0开始支持,但iPhone上直到iOS 8.0也支持,但行为不同),我们需要注意在iPhone上分栏控制器会以折叠的方式显示,因此我们需要检查当前设备是否是iPad,或者当前分栏控制器是否在展开状态。 另外,我们还需要设置分栏控制器的委托,并在委托方法中处理不同设备、不同方向下的布局。 然而,在低版本(比如iOS 8.0)中,我们可能需要使用`primaryColumnWidth`(只读)和设置`preferredPrimaryColumnWidthFraction`来实现。 具体步骤: - 在创建splitVC后,设置`preferredPrimaryColumnWidthFraction`为0.5。 - 设置`maximumPrimaryColumnWidth`为无限大(这样就不会限制我们设置的比例),或者设置为一个具体的值(比如屏幕宽度的一半)。 同时,我们还需要考虑在分栏控制器展开时(非折叠状态)才生效,而在折叠状态下(比如iPhone竖屏)主视图会隐藏。 因此,我们可以在构建splitVC时设置这些属性,并确保在设备旋转时也能正确处理(通过委托方法调整)。 代码修改如下: </think>以下是针对分栏控制器宽度设置的完整解决方案,兼容 iOS 低版本(支持到 iOS 11): ### 分栏宽度设置方案 ```swift private func buildMessageNavi() -> BaseSplitViewController { let splitVC = BaseSplitViewController() // 创建视图控制器(略)... // 设置分栏控制器配置 splitVC.preferredDisplayMode = .oneBesideSecondary // ✅ 设置主视图宽度为50% if #available(iOS 11.0, *) { // iOS 11+ 推荐方法 splitVC.preferredPrimaryColumnWidthFraction = 0.5 splitVC.maximumPrimaryColumnWidth = .greatestFiniteMagnitude } else { // iOS 8-10 兼容方案 splitVC.minimumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.5 splitVC.maximumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.5 } // ✅ 处理设备旋转时的宽度适配 NotificationCenter.default.addObserver( forName: UIDevice.orientationDidChangeNotification, object: nil, queue: .main ) { [weak splitVC] _ in guard let splitVC = splitVC else { return } if #available(iOS 11.0, *) { // 旋转后保持比例 splitVC.preferredPrimaryColumnWidthFraction = 0.5 } else { // 低版本手动调整 splitVC.minimumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.5 splitVC.maximumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.5 } } return splitVC } ``` ### 完整配置方法(含兼容处理) ```swift private func buildMessageNavi() -> BaseSplitViewController { // 创建分栏视图控制器 let splitVC = BaseSplitViewController() // 创建视图控制器 let messageVC = UIStoryboard(name: MessageStoryboardName, bundle: nil) .instantiateViewController(withIdentifier: MessageHomeVCStoryboardId) // ✅ 确保创建不同的实例 let masterVC = messageVC let detailVC = UIStoryboard(name: MessageStoryboardName, bundle: nil) .instantiateViewController(withIdentifier: "MessageDetailPlaceholderVC") // 创建新的实例 // 包装导航控制器 let masterNavi = BaseNavigationController(rootViewController: masterVC) let detailNavi = BaseNavigationController(rootViewController: detailVC) // 设置视图控制器数组 splitVC.viewControllers = [masterNavi, detailNavi] // 显示模式配置 splitVC.preferredDisplayMode = .oneBesideSecondary // ===== 宽度设置核心部分 ===== // 方案1: iOS 11+ 现代方法 if #available(iOS 11.0, *) { splitVC.preferredPrimaryColumnWidthFraction = 0.5 // 50%宽度 splitVC.maximumPrimaryColumnWidth = .greatestFiniteMagnitude // 不限制最大宽度 } // 方案2: iOS 8-10 兼容方案 else { let screenWidth = UIScreen.main.bounds.width splitVC.minimumPrimaryColumnWidth = screenWidth * 0.5 splitVC.maximumPrimaryColumnWidth = screenWidth * 0.5 // 添加旋转监听 NotificationCenter.default.addObserver( forName: UIDevice.orientationDidChangeNotification, object: nil, queue: .main ) { [weak splitVC] _ in let newWidth = UIScreen.main.bounds.width * 0.5 splitVC?.minimumPrimaryColumnWidth = newWidth splitVC?.maximumPrimaryColumnWidth = newWidth } } // ✅ 委托设置(必需) splitVC.delegate = self return splitVC } // ✅ 实现分栏控制器委托 extension YourViewController: UISplitViewControllerDelegate { // 确保主视图在需要时显示 func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool { return true } // 处理宽度变化 @available(iOS, introduced: 8.0, deprecated: 11.0) func targetDisplayModeForAction(in svc: UISplitViewController) -> UISplitViewController.DisplayMode { return .allVisible } } ``` ### 额外注意事项 1. **iPhone 兼容处理**: ```swift // 在详情控制器中添加返回按钮 override func viewDidLoad() { super.viewDidLoad() if splitViewController?.isCollapsed == true { navigationItem.leftBarButtonItem = UIBarButtonItem( title: "返回", style: .plain, target: self, action: #selector(didTapBack) ) } } ``` 2. **旋转后刷新布局**: ```swift // 在分栏控制器中 override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate { _ in if #available(iOS 11.0, *) { self.preferredPrimaryColumnWidthFraction = 0.5 } else { let newWidth = size.width * 0.5 self.minimumPrimaryColumnWidth = newWidth self.maximumPrimaryColumnWidth = newWidth } } } ``` 3. **低版本特殊处理**: ```swift // 对于iOS 10及以下,需要手动重置分割线 if #unavailable(iOS 11.0) { splitVC.view.layoutIfNeeded() DispatchQueue.main.async { splitVC.view.setNeedsLayout() } } ``` ### 调试建议 添加可视化边界辅助调试: ```swift // 在视图控制器中 masterVC.view.layer.borderWidth = 2 masterVC.view.layer.borderColor = UIColor.red.cgColor detailVC.view.layer.borderWidth = 2 detailVC.view.layer.borderColor = UIColor.blue.cgColor ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值