iOS16/Xcode14中如何控制/关闭UIScrollView随FirstResponder自动滚动?
解决iOS 16/Xcode 14中UIScrollView自动滚动至firstResponder的问题
iOS 16(对应Xcode 14版本)确实新增了UIScrollView的自动滚动特性:当滚动视图内的控件(如UITextField)成为firstResponder时,系统会自动触发滚动,将控件移至可见区域。针对你遇到的滚动幅度不足、需要禁用该行为的需求,以下是几种可行的解决方案:
方案1:重写UIScrollView拦截系统滚动请求
创建UIScrollView的子类,通过重写scrollRectToVisible(_:animated:)方法拦截系统触发的自动滚动。如果需要完全禁用该行为,直接不调用父类实现即可;如果需要区分手动滚动和系统自动滚动,可以添加标记逻辑:
完全禁用自动滚动
class CustomScrollView: UIScrollView { override func scrollRectToVisible(_ rect: CGRect, animated: Bool) { // 不调用super,直接拦截所有系统触发的自动滚动 } }
区分手动/系统滚动(保留手动滚动)
class CustomScrollView: UIScrollView { // 标记是否允许自动滚动 var allowAutoScroll = true override func scrollRectToVisible(_ rect: CGRect, animated: Bool) { if allowAutoScroll { super.scrollRectToVisible(rect, animated: animated) } } } // 在ViewController中使用 @IBAction func activateTextField() { scrollView.allowAutoScroll = false targetTextField.becomeFirstResponder() scrollView.allowAutoScroll = true }
方案2:手动处理键盘弹出时的滚动位置
如果只是系统滚动幅度不足,可自行监听键盘通知,计算并调整滚动偏移量,确保文本框完全避开键盘:
class ViewController: UIViewController { @IBOutlet weak var scrollView: UIScrollView! @IBOutlet weak var targetTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() // 注册键盘弹出通知 NotificationCenter.default.addObserver( self, selector: #selector(handleKeyboardShow), name: UIResponder.keyboardWillShowNotification, object: nil ) } @objc private func handleKeyboardShow(_ notification: Notification) { guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } let keyboardHeight = keyboardFrame.height // 转换文本框坐标到scrollView坐标系 let textFieldFrameInScrollView = targetTextField.convert(targetTextField.bounds, to: scrollView) let visibleArea = scrollView.bounds.inset(by: scrollView.contentInset) // 计算文本框底部与可见区域底部的差值 let bottomGap = visibleArea.maxY - textFieldFrameInScrollView.maxY if bottomGap < 0 { // 需要向上滚动的偏移量 let neededOffsetY = scrollView.contentOffset.y - bottomGap scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: neededOffsetY), animated: true) } } }
方案3:调整UIScrollView的内容适配行为
设置contentInsetAdjustmentBehavior为.never,可禁用系统基于安全区和键盘的自动内容偏移调整,但需手动处理滚动视图的contentInset以适配安全区:
scrollView.contentInsetAdjustmentBehavior = .never // 手动设置安全区适配 scrollView.contentInset = UIEdgeInsets(top: view.safeAreaInsets.top, left: 0, bottom: view.safeAreaInsets.bottom, right: 0) scrollView.scrollIndicatorInsets = scrollView.contentInset
内容的提问来源于stack exchange,提问作者Andrei Herford
相关产品推荐
相关产品推荐

