iPhone X键盘适配问题:调整视图origin.y后内容被状态栏遮挡
解决iPhone X上视图被状态栏遮挡的问题
嘿,我明白你遇到的问题了——直接修改containerView.frame.origin.y来适配键盘弹出,结果在iPhone X这类带刘海的设备上,视图跑到状态栏后面去了对吧?这其实是因为没考虑苹果引入的安全区域(Safe Area),下面给你两个实用的解决办法:
1. 改用AutoLayout约束(最推荐的方案)
直接改frame在AutoLayout环境下很容易踩坑,尤其是安全区域适配这块。不如给containerView加个底部约束,通过调整约束值来适配键盘,这样完全不会碰到底部或顶部的安全区域问题:
操作步骤:
- 先给
containerView添加一个底部约束(连到父视图的安全区域底部),然后把这个约束做成IBOutlet,比如命名为containerBottomConstraint - 然后修改你的键盘通知代码:
@objc func keyboardWillShow(notification: NSNotification) { guard let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return } let keyboardHeight = keyboardFrame.cgRectValue.height // 减去底部安全区域的高度,避免视图被底部的Home Indicator挡住 let bottomSafeInset = view.safeAreaInsets.bottom containerBottomConstraint.constant = keyboardHeight - bottomSafeInset // 加上动画,和键盘弹出的节奏保持一致 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } } @objc func keyboardWillHide(notification: NSNotification) { containerBottomConstraint.constant = 0 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } }
用这种方式,containerView只会在安全区域范围内移动,绝对不会跑到状态栏后面去。
2. 如果坚持用frame调整,记得加上安全区域判断
要是你暂时不想改AutoLayout,那调整origin.y的时候,得确保视图顶部不超过安全区域的顶部边界:
@objc func keyboardWillShow(notification: NSNotification) { guard let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return } if !keyboardShown { // 获取顶部安全区域高度——iPhone X及以后是44pt,老设备是20pt let topSafeHeight = view.safeAreaInsets.top // 计算最多能往上移多少,不能让视图顶部超过安全区域的顶部 let maxMoveUpDistance = containerView.frame.origin.y - topSafeHeight // 实际移动距离取键盘高度和最大可移动距离的最小值,防止移太多 let actualMoveDistance = min(keyboardSize.height, maxMoveUpDistance) self.containerView.frame.origin.y -= actualMoveDistance keyboardShown = true } }
另外还要注意,键盘的高度其实已经包含了底部安全区域的高度,所以如果你的containerView原本是贴在安全区域底部的,直接减键盘高度会多移了底部安全区域的高度,这时候应该用键盘高度 - 底部安全区域高度来计算移动距离哦。
额外提醒
- 建议注册
UIKeyboardWillChangeFrameNotification代替keyboardWillShow,因为键盘高度可能会变化(比如切换输入法、启用听写) - 别忘了在页面销毁的时候移除通知监听,避免内存泄漏:
deinit { NotificationCenter.default.removeObserver(self) }
内容的提问来源于stack exchange,提问作者FarisZ
相关产品推荐
相关产品推荐

