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

点击Return后键盘高度变化,ScrollView滚动异常问题求助

我太懂这种反复操作后布局掉链子的烦恼了!你遇到的问题大概率是键盘收起时没正确重置ScrollView的布局参数,或者滚动逻辑有遗漏,咱们一步步来修复:

一、先补全键盘收起时的重置逻辑

你大概率只处理了键盘弹出时的contentInset设置,却没在键盘收起时把ScrollView的参数还原回去,这会导致第二次触发时布局计算混乱。先补上键盘收起的处理方法:

@objc func keyboardWillBeHidden(_ notification: Notification) {
    guard let userInfo = notification.userInfo else { return }
    let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double ?? 0.25
    
    UIView.animate(withDuration: animationDuration) {
        // 重置contentInset和滚动指示器的Insets为初始值
        self.scrollView.contentInset = .zero
        self.scrollView.scrollIndicatorInsets = .zero
        // 可选:如果需要让页面回到初始位置,加上这行
        self.scrollView.contentOffset = .zero
    }
}

别忘了在注册通知的时候把这个方法加上:

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
二、优化键盘弹出时的滚动计算逻辑

有时候第一次滚动后,ScrollView的contentOffset没有正确重置,第二次弹出时就会计算错误。可以主动计算TextField需要的滚动偏移量,确保它完全显示在键盘上方:

@objc func keyboardWasShown(_ notification: Notification) {
    guard let userInfo = notification.userInfo else { return }
    let keyboardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue ?? .zero
    let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double ?? 0.25
    let keyboardHeight = keyboardFrame.height
    
    // 计算TextField在ScrollView坐标系中的位置
    let textFieldFrameInScroll = scrollView.convert(bottomTextField.frame, from: bottomTextField.superview)
    // 算出需要滚动的偏移量,确保TextField底部不被键盘挡住
    let requiredOffset = textFieldFrameInScroll.maxY - (scrollView.bounds.height - keyboardHeight)
    
    UIView.animate(withDuration: animationDuration) {
        self.scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardHeight, right: 0)
        self.scrollView.scrollIndicatorInsets = self.scrollView.contentInset
        
        // 如果需要滚动,就主动调整contentOffset
        if requiredOffset > 0 {
            self.scrollView.contentOffset = CGPoint(x: 0, y: requiredOffset)
        }
    }
}
三、额外的避坑提示
  • 记得在页面销毁时移除通知观察者,避免内存泄漏:
deinit {
    NotificationCenter.default.removeObserver(self)
}
  • 建议把键盘弹出的监听通知换成UIResponder.keyboardWillShowNotification,用willShow的时机比didShow更提前,能避免布局延迟导致的滚动不及时。
  • 如果你的ScrollView用了AutoLayout,不要给它的底部设置固定到父视图底部的约束,留足弹性空间才不会和contentInset的设置冲突。

这样调整后,第二次点击底部TextField时,ScrollView应该能正确计算滚动幅度,确保TextField不会被键盘遮挡了。

内容的提问来源于stack exchange,提问作者wm.p1us

火山引擎 最新活动