问题描述
当我从一个文本字段点击到另一个文本字段时,它会滚动以使上一个文本视图成为焦点。我尝试通过观察键盘更改通知来对此做出响应,并注意到UIResponder.keyboardWillChangeFrameNotification
被调用了两次。在第一个文本视图仍然是第一响应者的同时,一次在第二个文本视图是第一响应者的时候。
如果有人想对此采取行动,我创建了最少的代码来重现我所看到的问题。启动一个新的单页应用程序,并将其粘贴到ViewController.swift。
import UIKit
class ViewController: UIViewController {
override func loadView() {
view = ScrollView()
}
}
class ScrollView: UIScrollView {
lazy var stack: UIStackView = {
let stack = UIStackView()
stack.backgroundColor = .systemGroupedBackground
stack.axis = .vertical
stack.spacing = 32
for number in 1...50 {
let textField = UITextField()
textField.text = "\(number)"
textField.borderStyle = .roundedRect
textField.heightAnchor.constraint(equalToConstant: 44).isActive = true
stack.addArrangedSubview(textField)
}
return stack
}()
init() {
super.init(frame: .zero)
addSubview(stack)
stack.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stack.topAnchor.constraint(equalTo: topAnchor),stack.bottomAnchor.constraint(equalTo: bottomAnchor),stack.leadingAnchor.constraint(equalTo: leadingAnchor),stack.trailingAnchor.constraint(equalTo: trailingAnchor),stack.widthAnchor.constraint(equalTo: widthAnchor)
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
解决方法
我不知道为什么iOS 14会采用这种方式,以及它的意图还是错误。他们能够解决该问题的方法是将UIScrollView
子类化并覆盖setContentOffset
无所事事。这是我正在谈论的示例。
class ScrollView: UIScrollView {
func forceContentOffset(_ contentOffset: CGPoint,animated: Bool) {
super.setContentOffset(contentOffset,animated: animated)
}
override func setContentOffset(_ contentOffset: CGPoint,animated: Bool) {
// Intentially left blank to block the system from changing the content offset
}
}
这使您可以手动确定何时滚动滚动视图,但它需要植入任何您想保留的自动行为。