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

如何让UITextField在视图出现时归位并在键盘弹出时即时显示?

解决UITextField键盘弹出滑入显示及视图恢复初始位置问题

问题根源

  • 键盘弹出时UITextField滑入:keyboardWillShow通知在键盘展开动画期间触发,直接修改frame会被系统自动添加上动画,导致跟随键盘滑入。
  • 视图出现时未重置位置:当前代码未在视图生命周期中处理UITextField的初始位置恢复,且键盘隐藏时的位置设置(y:5000)为不合理的硬编码。

解决方案

1. 让UITextField即时显示(无滑入动画)

提供两种实现方式,选其一即可:

方式一:改用keyboardDidShow通知

该通知在键盘完全显示后触发,此时修改frame不会带有动画:

func registerKeyboardNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow(_:)), name: UIResponder.keyboardDidShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardDidShow(_ notification: Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let textFieldOrigin = CGPoint(x: 0, y: keyboardSize.origin.y - inputTextField.frame.height)
        inputTextField.frame.origin = textFieldOrigin
    }
}

方式二:禁用动画修改frame

如果仍想保留keyboardWillShow,可以在修改frame时禁用UI动画,强制即时更新位置:

@objc func keyboardWillShow(_ notification: Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let textFieldOrigin = CGPoint(x: 0, y: keyboardSize.origin.y - inputTextField.frame.height)
        
        UIView.performWithoutAnimation {
            inputTextField.frame.origin = textFieldOrigin
        }
    }
}

2. 视图出现时恢复初始位置

在viewWillAppear中重置UITextField到初始位置,同时修正键盘隐藏时的位置设置:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // 重置到初始位置
    inputTextField.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50)
}

@objc func keyboardWillHide(_ notification: Notification) {
    // 回到初始位置,替换原有的y:5000硬编码
    inputTextField.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50)
    inputTextField.resignFirstResponder()
}

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

在控制器销毁时移除通知观察者:

deinit {
    NotificationCenter.default.removeObserver(self)
}

完整优化代码

class YourViewController: UIViewController {
    var inputTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupTextField()
        registerKeyboardNotifications()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        inputTextField.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50)
    }

    func setupTextField() {
        inputTextField = UITextField(frame: CGRect(x:0, y: 0, width: UIScreen.main.bounds.width, height: 50))
        inputTextField.font = UIFont.systemFont(ofSize: 15)
        inputTextField.backgroundColor = .white
        inputTextField.borderStyle = .bezel
        inputTextField.contentVerticalAlignment = .center
        view.addSubview(inputTextField)
    }

    func registerKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow(_:)), name: UIResponder.keyboardDidShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    @objc func keyboardDidShow(_ notification: Notification) {
        guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
        inputTextField.frame.origin.y = keyboardSize.origin.y - inputTextField.frame.height
    }

    @objc func keyboardWillHide(_ notification: Notification) {
        inputTextField.frame.origin.y = 0
        inputTextField.resignFirstResponder()
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 19:04:53