IQKeyboardManager使用问题:如何让UINavigationBar固定在顶部
我之前做聊天应用时也碰到过一模一样的问题——IQKeyboardManager处理键盘交互确实省心,但默认配置会把整个导航控制器的视图都往上推,视觉效果特别怪异。给你几个亲测有效的解决办法,你可以根据项目情况选:
方法一:全局配置,让IQKeyboardManager忽略导航控制器
如果所有页面都不想让导航栏跟着键盘动,直接在AppDelegate或者项目初始化的地方加几行配置即可:
import IQKeyboardManagerSwift func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 开启IQKeyboardManager核心功能 IQKeyboardManager.shared.enable = true // 禁止它处理导航控制器的视图移动逻辑 IQKeyboardManager.shared.disabledDistanceHandlingClasses = [UINavigationController.self] return true }
设置后,IQKeyboardManager只会调整当前控制器的内容区域,不会触碰导航栏。
方法二:仅在聊天页面禁用全局调整,手动处理滚动视图
如果其他页面需要保留IQKeyboardManager的默认行为,只针对聊天页面修改的话,可以这么做:
首先在聊天ViewController的viewDidLoad里禁用当前控制器的自动调整,然后监听键盘通知手动调整UICollectionView的内边距:
override func viewDidLoad() { super.viewDidLoad() // 让IQKeyboardManager跳过当前控制器的全局视图调整 IQKeyboardManager.shared.disabledViewControllerClasses = [ChatViewController.self] // 监听键盘弹出/收起通知 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) // iOS11+ 配置滚动视图的内边距调整行为,确保布局正确 collectionView.contentInsetAdjustmentBehavior = .scrollableAxes } // 键盘弹出时调整集合视图内边距,让内容不被键盘遮挡 @objc private func keyboardWillShow(_ notification: Notification) { guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } let keyboardHeight = keyboardFrame.height let inset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardHeight, right: 0) collectionView.contentInset = inset collectionView.scrollIndicatorInsets = inset // 可选:自动滚动到最新消息,提升聊天体验 if let lastIndexPath = collectionView.indexPathsForVisibleItems.last { collectionView.scrollToItem(at: lastIndexPath, at: .bottom, animated: true) } } // 键盘收起时恢复内边距 @objc private func keyboardWillHide(_ notification: Notification) { collectionView.contentInset = .zero collectionView.scrollIndicatorInsets = .zero }
记得在deinit里移除通知观察者,避免内存泄漏:
deinit { NotificationCenter.default.removeObserver(self) }
方法三:设置导航栏为不透明(最简单的方案)
如果你的导航栏不需要半透明效果,这个方法最省心。只要在聊天ViewController里设置导航栏不透明,IQKeyboardManager就会自动识别,只调整下方的内容视图:
override func viewDidLoad() { super.viewDidLoad() // 关闭导航栏半透明属性 navigationController?.navigationBar.isTranslucent = false // 设置导航栏背景色(根据你的设计需求修改) navigationController?.navigationBar.barTintColor = .systemBackground // 确保视图布局从导航栏下方开始(用AutoLayout约束到safeAreaTop即可) }
这个方法不需要修改IQKeyboardManager的任何配置,只要导航栏不透明,它就不会把导航栏算进可移动的区域里,我当时就是用这个方法快速解决的问题!
内容的提问来源于stack exchange,提问作者FS.O6
相关产品推荐
相关产品推荐

