如何让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
相关产品推荐
相关产品推荐

