如何使用 iOS 上的约束将视图附加到键盘顶部边缘 [英] How can I attach view to keyboard top edge using constraints on iOS
本文介绍了如何使用 iOS 上的约束将视图附加到键盘顶部边缘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个简单的视图附加到视图控制器的底部:
I have a simple view attached to the bottom of view controller:
let view = UIView()
view.backgroundColor = .gray
view.translatesAutoresizingMaskIntoConstraints = false
let viewBottomPositionConstraint = view.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor)
NSLayoutConstraint.activate([
view.heightAnchor.constraint(equalToConstant: 100),
view.leftAnchor.constraint(equalTo: self.view.leftAnchor),
view.rightAnchor.constraint(equalTo: self.view.rightAnchor),
viewBottomPositionConstraint
])
当键盘在键盘动画后出现/消失时,我需要该视图上下移动
I need that view to go up and down when keyboard appears/disappears following keyboard animation
推荐答案
我已经创建了KeyboardNotifier
,用法很简单:
I've created KeyboardNotifier
, usage is pretty simple:
var keyboardNotifier: KeyboardNotifier!
override func viewDidLoad() {
super.viewDidLoad()
keyboardNotifier = KeyboardNotifier(parentView: view, constraint: viewBottomPositionConstraint)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
keyboardNotifier.enabled = true
override func viewDidDisappear(_ animated: Bool) {
keyboardNotifier.enabled = false
super.viewDidDisappear(animated)
}
它应该在 viewWillAppear
/viewDidDisappear
中启用/禁用以防止在其他屏幕上交互.
It should be enabled/disabled in viewWillAppear
/viewDidDisappear
to prevent interactions on other screens.
通过监听 keyboardWillChangeFrameNotification
我不得不将它从键盘创建的动画中移出以防止出现故障,并同时更新我自己动画中的约束.
I had to move it out of the animation created by keyboard to prevent glitches, and updating constraint in my own animation in parallel.
final class KeyboardNotifier {
var enabled: Bool = true {
didSet {
setNeedsUpdateConstraint()
}
}
init(
parentView: UIView,
constraint: NSLayoutConstraint
) {
self.parentView = parentView
self.constraint = constraint
baseConstant = constraint.constant
notificationObserver = NotificationCenter.default
.addObserver(
forName: UIResponder.keyboardWillChangeFrameNotification,
object: nil,
queue: .main
) { [weak self] in
self?.keyboardEndFrame = ($0.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
self?.setNeedsUpdateConstraint(animationDuration: UIView.inheritedAnimationDuration)
}
}
private weak var parentView: UIView?
private weak var constraint: NSLayoutConstraint?
private let baseConstant: CGFloat
private var notificationObserver: NSObjectProtocol!
private var keyboardEndFrame: CGRect?
private var latestAnimationDuration: TimeInterval?
private func setNeedsUpdateConstraint(animationDuration: TimeInterval = 0) {
guard
latestAnimationDuration == nil
|| animationDuration > latestAnimationDuration!
else { return }
let shouldUpdate = latestAnimationDuration == nil
latestAnimationDuration = animationDuration
if shouldUpdate {
DispatchQueue.main.async {
self.updateConstraint()
}
}
}
private func updateConstraint() {
defer {
latestAnimationDuration = nil
}
guard
let latestAnimationDuration = latestAnimationDuration,
enabled,
let keyboardEndFrame = keyboardEndFrame,
let parentView = parentView,
let constraint = constraint
else { return }
UIView.performWithoutAnimation {
parentView.layoutIfNeeded()
}
let isParentFirstItem = constraint.firstItem is UILayoutGuide || constraint.firstItem === parentView
let followsLayoutGuide = constraint.firstItem is UILayoutGuide || constraint.secondItem is UILayoutGuide
let multiplierSign: CGFloat = isParentFirstItem ? 1 : -1
let screenHeight = UIScreen.main.bounds.height
if keyboardEndFrame.minY >= screenHeight {
constraint.constant = baseConstant
} else {
let safeAreaInsets = (followsLayoutGuide ? parentView.safeAreaInsets.bottom : 0)
// if our constraint makes view invisible when keyboard is hidden, we need to ignore it
let fixedBaseConstant = max(multiplierSign * baseConstant, 0)
constraint.constant = multiplierSign * (screenHeight - keyboardEndFrame.minY - safeAreaInsets + fixedBaseConstant)
}
UIView.animate(
withDuration: latestAnimationDuration,
delay: 0,
options: .beginFromCurrentState,
animations: { parentView.layoutIfNeeded() },
completion: nil
)
}
}
这篇关于如何使用 iOS 上的约束将视图附加到键盘顶部边缘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文