You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在存在自定义输入辅助视图时独立检测原生键盘高度?

解决自定义输入辅助视图下原生键盘高度的解耦方案

嘿,这个问题我之前在做带自定义输入辅助视图的键盘适配时也踩过坑,硬编码辅助视图高度不仅维护麻烦,还容易在不同设备/系统版本出问题,分享几个我亲测好用的解耦方案:

方案1:通过当前第一响应者动态获取辅助视图高度

核心思路是:当键盘弹出时,找到当前的第一响应者(比如UITextField/UITextView),直接获取它绑定的自定义输入辅助视图的高度,再从通知返回的总高度中减去,得到原生键盘高度。

首先需要实现一个获取当前第一响应者的扩展:

extension UIResponder {
    static func currentFirstResponder() -> UIResponder? {
        _currentFirstResponder = nil
        UIApplication.shared.sendAction(#selector(findFirstResponder(_:)), to: nil, from: nil, for: nil)
        return _currentFirstResponder
    }
    
    private static weak var _currentFirstResponder: UIResponder?
    
    @objc private func findFirstResponder(_ sender: Any) {
        UIResponder._currentFirstResponder = self
    }
}

然后修改你的键盘通知回调:

NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { [weak self] notification in
    guard let userInfo = notification.userInfo,
          let keyboardFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect,
          let firstResponder = UIResponder.currentFirstResponder() as? UIView,
          let accessoryHeight = firstResponder.inputAccessoryView?.bounds.height else {
        return
    }
    
    // 计算得到原生键盘的真实高度
    let nativeKeyboardHeight = keyboardFrame.size.height - accessoryHeight
    // 这里写你的高度适配逻辑
}

这个方案不需要硬编码任何高度值,完全依赖系统视图的实际尺寸,兼容性很好。

方案2:利用UIKeyboardLayoutGuide(iOS 11+)

iOS 11之后苹果引入了UIKeyboardLayoutGuide,这个布局指南的高度就是原生键盘的纯高度(不包含自定义输入辅助视图),直接用它就能跳过计算步骤,非常省心。

在你的ViewController中可以这样用:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 绑定布局约束(示例:让某个视图贴在键盘顶部)
    NSLayoutConstraint.activate([
        yourCustomView.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor)
    ])
    
    // 如果需要主动获取高度,可以监听布局指南的frame变化
    NotificationCenter.default.addObserver(forName: NSNotification.Name.UILayoutGuideFrameDidChange, object: view.keyboardLayoutGuide, queue: .main) { [weak self] _ in
        let nativeKeyboardHeight = self?.view.keyboardLayoutGuide.layoutFrame.height ?? 0
        // 处理高度逻辑
    }
}

这个方案是苹果官方推荐的,代码最简洁,没有计算成本,唯一限制是需要支持iOS 11及以上版本。

方案3:预加载原生键盘高度(兼容旧版本)

如果需要兼容iOS 10及以下,可以用一个小技巧:临时创建一个不带输入辅助视图的输入框,触发键盘弹出,记录原生键盘高度后再收起。

private var cachedNativeKeyboardHeight: CGFloat = 0

func preloadNativeKeyboardHeight() {
    // 创建临时输入框,放在屏幕外避免视觉干扰
    let tempTextField = UITextField(frame: CGRect(x: -1000, y: -1000, width: 0, height: 0))
    tempTextField.inputAccessoryView = nil // 确保没有附加辅助视图
    view.addSubview(tempTextField)
    
    // 监听键盘弹出通知
    let observer = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { [weak self, weak tempTextField] notification in
        guard let userInfo = notification.userInfo,
              let keyboardFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect else {
            return
        }
        // 缓存原生键盘高度
        self?.cachedNativeKeyboardHeight = keyboardFrame.size.height
        // 收起键盘并移除临时视图
        tempTextField?.resignFirstResponder()
        tempTextField?.removeFromSuperview()
        // 移除临时观察者
        NotificationCenter.default.removeObserver(observer)
    }
    
    // 触发键盘弹出
    tempTextField.becomeFirstResponder()
}

可以在App启动或ViewController初始化时调用这个方法预加载,之后直接用缓存的高度即可。缺点是会有一次短暂的键盘弹出(但因为视图在屏幕外,用户看不到),适合旧版本兼容场景。


内容的提问来源于stack exchange,提问作者Milan Nosáľ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:44:28