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

输入文本时TextField被键盘遮挡的技术问题求助

嘿,我来帮你搞定这个TextField被键盘遮挡的问题!看起来你已经尝试监听键盘通知了,但可能在实现细节上出了点小问题,我给你梳理下完整的解决方案,结合你现有的代码来调整:

解决TextField被键盘遮挡的问题

1. 完善键盘通知的监听与处理

你已经添加了键盘通知的观察者,但代码似乎被截断了。首先得确保注册完整的键盘通知,再实现对应的处理逻辑:

先补全viewDidLoad里的通知注册:

override func viewDidLoad() {
    super.viewDidLoad()
    // 监听键盘弹出/帧变化通知
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardFrameChangeNotification(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    // 监听键盘收起通知
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    
    // 你的其他现有代码...
}

然后实现两个通知的处理方法,核心是计算view需要偏移的距离,让当前输入的TextField避开键盘:

@objc func keyboardFrameChangeNotification(_ notification: Notification) {
    guard let userInfo = notification.userInfo,
          let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
          let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval else {
        return
    }
    
    // 获取当前正在输入的TextField
    guard let activeTextField = UIResponder.currentFirst() as? UITextField else { return }
    // 转换TextField的frame到当前ViewController的view坐标系
    let textFieldFrame = activeTextField.convert(activeTextField.bounds, to: self.view)
    // 计算TextField底部到view底部的距离,对比键盘高度判断是否重叠
    let textFieldBottom = textFieldFrame.origin.y + textFieldFrame.size.height
    let availableViewHeight = self.view.bounds.size.height - keyboardFrame.size.height
    let overlap = textFieldBottom - availableViewHeight
    
    // 如果有重叠,就动画偏移view;否则不处理
    if overlap > 0 {
        UIView.animate(withDuration: duration) {
            self.view.transform = CGAffineTransform(translationX: 0, y: -overlap)
        }
    }
}

@objc func keyboardWillHideNotification(_ notification: Notification) {
    guard let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval else {
        return
    }
    // 键盘收起时,恢复view的原始位置
    UIView.animate(withDuration: duration) {
        self.view.transform = .identity
    }
}

这里需要一个小工具方法来获取当前的第一响应者,你可以给UIResponder加个扩展:

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

2. 适配TableView场景下的TextField

如果你的TextField是放在TableViewCell里的,除了上面的view偏移,还需要在编辑时滚动到对应的cell位置,避免被遮挡:

func textFieldDidBeginEditing(_ textField: UITextField) {
    // 找到TextField所在的cell的indexPath
    guard let cell = textField.superview?.superview as? UITableViewCell,
          let indexPath = yourTableView.indexPath(for: cell) else { return }
    // 滚动到该cell,确保它在可视区域
    yourTableView.scrollToRow(at: indexPath, at: .middle, animated: true)
}

3. 清理通知观察者避免内存泄漏

记得在ViewController销毁时移除通知观察者:

deinit {
    NotificationCenter.default.removeObserver(self)
}

这样调整后,键盘弹出时你的view会自动偏移合适的距离,让当前输入的TextField显示在键盘上方;键盘收起时恢复原位。如果是TableView里的TextField,滚动逻辑也能确保它不被遮挡。

内容的提问来源于stack exchange,提问作者Yrb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:04:34