You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS UITextField输入文本时定位重置问题求助

解决iOS UITextField编辑时的键盘遮挡/屏幕上移问题

嘿,我完全懂这种被Auto Layout和键盘交互折腾得抓耳挠腮的感觉!你碰到的这个问题其实很常见,本质是键盘弹出时没有正确调整界面布局,要么让输入框被挡住,要么把整个内容顶得乱七八糟。下面给你分享几个原生的解决方案,亲测有效:

方案一:用UIScrollView包裹内容(最稳妥的原生方案)

这是处理键盘遮挡问题的标准做法,既能让输入框自动滚动到可视区域,又能避免整个屏幕乱移:

  1. 重构布局结构

    • 把你原来的图片、UITextField全部放到一个UIScrollView里面(如果有其他元素也一起放进去)。
    • UIScrollView设置和父视图(比如ViewController的view)四边完全对齐的约束,确保它占满整个屏幕。
    • UIScrollView内部添加一个contentView(UIView),给contentView设置这几个关键约束:
      • 顶部、底部、左侧、右侧和scrollView的对应边缘对齐
      • contentView的宽度等于scrollView的宽度(防止横向滚动)
      • contentView的高度可以根据内部元素的约束自动撑开,不用手动设置
  2. 监听键盘通知,动态调整scrollView的内边距
    在你的ViewController里添加以下代码:

    override func viewDidLoad() {
        super.viewDidLoad()
        // 注册键盘通知
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    @objc private func keyboardWillShow(notification: NSNotification) {
        guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
        // 获取键盘高度,注意要转换为当前视图的坐标系
        let keyboardHeight = view.convert(keyboardFrame, from: nil).height
        // 设置scrollView的底部内边距,让内容能避开键盘
        scrollView.contentInset.bottom = keyboardHeight
        scrollView.scrollIndicatorInsets.bottom = keyboardHeight
        
        // 让当前编辑的UITextField滚动到可视区域
        if let activeTextField = UIResponder.currentFirstResponder as? UITextField {
            scrollView.scrollRectToVisible(activeTextField.frame, animated: true)
        }
    }
    
    @objc private func keyboardWillHide(notification: NSNotification) {
        // 键盘收起时恢复内边距
        scrollView.contentInset.bottom = .zero
        scrollView.scrollIndicatorInsets.bottom = .zero
    }
    
    // 别忘了在deinit里移除通知
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    

    这里用到的currentFirstResponder是一个UIResponder的扩展,你可以自己实现:

    extension UIResponder {
        static weak var 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
        }
    }
    

方案二:关闭系统自动调整(解决屏幕整体上移的问题)

如果你的界面已经用了UIScrollView,但还是出现整个屏幕上移、图片显示异常的情况,大概率是系统的自动调整内边距在搞鬼:

  • iOS 11及以后:设置scrollView.contentInsetAdjustmentBehavior = .never,这样系统就不会自动给scrollView添加额外的内边距,避免内容被顶上去。
  • iOS 11以前:设置automaticallyAdjustsScrollViewInsets = false(这个属性已经废弃,但旧版本还能用)

额外注意事项

  • 确保你的UITextField的底部约束是和contentView的底部对齐(或者和其他元素有合理的间距),这样scrollView的contentSize才能正确计算,输入框才能被滚动到可视区域。
  • 如果不想用scrollView,也可以单独给UITextField的底部约束添加IBOutlet,在键盘弹出时修改约束的constant值,把输入框往上推。但这种方法不如scrollView灵活,尤其是界面元素多的时候。

希望这些方法能帮你解决问题!我之前碰到几乎一样的场景,用第一个方案就完美搞定了😉

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

火山引擎 最新活动