完善任务流程、键盘适配与页面交互
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
import SnapKit
|
||||
import UIKit
|
||||
|
||||
/// 自定义居中弹窗的键盘避让基类,负责在键盘弹出时同步移动内容卡片。
|
||||
/// 自定义居中弹窗的兼容基类,键盘避让由全局 `IQKeyboardManager` 统一处理。
|
||||
class KeyboardAvoidingDialogView: UIView {
|
||||
|
||||
/// 需要避让键盘的弹窗内容视图,通常是白色卡片容器。
|
||||
@ -18,8 +18,6 @@ class KeyboardAvoidingDialogView: UIView {
|
||||
/// 内容视图与屏幕顶部、键盘顶部之间保留的最小距离。
|
||||
var keyboardAvoidingMinimumSpacing: CGFloat = AppSpacing.md
|
||||
|
||||
private var keyboardObservers: [NSObjectProtocol] = []
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
}
|
||||
@ -29,77 +27,4 @@ class KeyboardAvoidingDialogView: UIView {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
unregisterKeyboardObservers()
|
||||
}
|
||||
|
||||
override func didMoveToSuperview() {
|
||||
super.didMoveToSuperview()
|
||||
if superview == nil {
|
||||
unregisterKeyboardObservers()
|
||||
} else {
|
||||
registerKeyboardObservers()
|
||||
}
|
||||
}
|
||||
|
||||
private func registerKeyboardObservers() {
|
||||
unregisterKeyboardObservers()
|
||||
let center = NotificationCenter.default
|
||||
keyboardObservers = [
|
||||
center.addObserver(
|
||||
forName: UIResponder.keyboardWillChangeFrameNotification,
|
||||
object: nil,
|
||||
queue: .main
|
||||
) { [weak self] notification in
|
||||
self?.handleKeyboardNotification(notification)
|
||||
},
|
||||
center.addObserver(
|
||||
forName: UIResponder.keyboardWillHideNotification,
|
||||
object: nil,
|
||||
queue: .main
|
||||
) { [weak self] notification in
|
||||
self?.handleKeyboardNotification(notification)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
private func unregisterKeyboardObservers() {
|
||||
keyboardObservers.forEach(NotificationCenter.default.removeObserver)
|
||||
keyboardObservers.removeAll()
|
||||
}
|
||||
|
||||
private func handleKeyboardNotification(_ notification: Notification) {
|
||||
layoutIfNeeded()
|
||||
guard let userInfo = notification.userInfo else { return }
|
||||
|
||||
let duration = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0.25
|
||||
let curveRaw = (userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue
|
||||
?? UInt(UIView.AnimationCurve.easeInOut.rawValue)
|
||||
let options = UIView.AnimationOptions(rawValue: curveRaw << 16)
|
||||
|
||||
keyboardAvoidingCenterYConstraint?.update(offset: keyboardAvoidanceOffset(from: userInfo))
|
||||
UIView.animate(withDuration: duration, delay: 0, options: options) {
|
||||
self.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
private func keyboardAvoidanceOffset(from userInfo: [AnyHashable: Any]) -> CGFloat {
|
||||
guard
|
||||
let contentView = keyboardAvoidingContentView,
|
||||
let keyboardFrameValue = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue
|
||||
else {
|
||||
return 0
|
||||
}
|
||||
|
||||
let keyboardFrame = convert(keyboardFrameValue.cgRectValue, from: nil)
|
||||
guard keyboardFrame.minY < bounds.height else { return 0 }
|
||||
|
||||
let contentHeight = contentView.bounds.height
|
||||
let baseMinY = bounds.midY - contentHeight / 2
|
||||
let baseMaxY = bounds.midY + contentHeight / 2
|
||||
let desiredBottom = keyboardFrame.minY - keyboardAvoidingMinimumSpacing
|
||||
let neededShift = max(0, baseMaxY - desiredBottom)
|
||||
let maxShift = max(0, baseMinY - keyboardAvoidingMinimumSpacing)
|
||||
return -min(neededShift, maxShift)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user