iPhone X中UITextView作为inputAccessoryView的键盘适配问题
解决iPhone X上InputAccessoryView与键盘底部行显示异常的问题
这个问题我之前做类似Messages的聊天界面时也踩过坑,根源其实是iPhone X这类全面屏设备的安全区域(Safe Area)布局差异——底部的Home Indicator区域会干扰键盘和inputAccessoryView的对齐计算,导致键盘底部的功能行(比如数字键、空格、回车)要么错位要么被遮挡。
下面是经过验证的解决方案,一步步来:
1. 用Auto Layout构建自定义InputAccessoryView
别再用frame硬写布局了,改用Auto Layout并绑定到安全区域,让系统能正确计算视图尺寸:
class ChatInputAccessoryView: UIView { let messageTextView = UITextView() override init(frame: CGRect) { super.init(frame: frame) setupUI() setupConstraints() } required init?(coder: NSCoder) { super.init(coder: coder) setupUI() setupConstraints() } private func setupUI() { backgroundColor = .systemBackground messageTextView.font = .systemFont(ofSize: 16) messageTextView.textContainerInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) addSubview(messageTextView) // 禁用自动转换,强制使用Auto Layout translatesAutoresizingMaskIntoConstraints = false } private func setupConstraints() { NSLayoutConstraint.activate([ // 文本框与父视图的边距 messageTextView.topAnchor.constraint(equalTo: topAnchor, constant: 8), messageTextView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12), messageTextView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12), // 关键:绑定到安全区域底部,适配Home Indicator messageTextView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -8), // 确保输入栏有最小高度,避免被压缩 heightAnchor.constraint(greaterThanOrEqualToConstant: 44) ]) } // 重写固有内容尺寸,让系统自动计算高度 override var intrinsicContentSize: CGSize { return CGSize(width: UIView.noIntrinsicMetric, height: UIView.noIntrinsicMetric) } }
2. 正确配置视图控制器的InputAccessoryView
确保视图控制器正确返回自定义输入栏,并且允许成为第一响应者:
class ChatViewController: UIViewController { private let inputAccessoryView = ChatInputAccessoryView() override var inputAccessoryView: UIView? { return inputAccessoryView } override var canBecomeFirstResponder: Bool { return true } override func viewDidLoad() { super.viewDidLoad() // 禁用自动调整滚动视图内边距(如果页面有滚动视图的话),避免布局冲突 automaticallyAdjustsScrollViewInsets = false } }
3. 键盘通知辅助修正布局(可选但推荐)
如果还是偶尔出现显示异常,可以监听键盘弹出通知,手动修正inputAccessoryView的位置,确保和键盘完全对齐:
override func viewDidLoad() { super.viewDidLoad() automaticallyAdjustsScrollViewInsets = false // 监听键盘弹出通知 NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil ) } @objc private func keyboardWillShow(_ notification: Notification) { guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } // 计算输入栏的正确位置:屏幕底部 - 键盘高度 - 输入栏高度 let inputViewY = view.bounds.height - keyboardFrame.height - inputAccessoryView.intrinsicContentSize.height inputAccessoryView.frame = CGRect( x: 0, y: inputViewY, width: view.bounds.width, height: inputAccessoryView.intrinsicContentSize.height ) }
4. 检查全局布局设置
- 确保Info.plist中的
View controller-based status bar appearance设置为YES,保证状态栏布局正确。 - 如果视图控制器嵌入在导航栏或TabBar中,建议把导航栏/TabBar的
isTranslucent设为true,让系统自动处理安全区域适配。
这套方案我之前在项目里用过,完美解决了iPhone X上的键盘显示异常问题,你可以试试。
内容的提问来源于stack exchange,提问作者nycurt
相关产品推荐
相关产品推荐

