修复任务提交与弹窗交互问题

This commit is contained in:
2026-07-10 14:51:34 +08:00
parent df547a16dc
commit f88a85a807
48 changed files with 1065 additions and 254 deletions

View File

@ -0,0 +1,105 @@
//
// KeyboardAvoidingDialogView.swift
// suixinkan
//
import SnapKit
import UIKit
///
class KeyboardAvoidingDialogView: UIView {
///
var keyboardAvoidingContentView: UIView?
/// centerY
var keyboardAvoidingCenterYConstraint: Constraint?
///
var keyboardAvoidingMinimumSpacing: CGFloat = AppSpacing.md
private var keyboardObservers: [NSObjectProtocol] = []
override init(frame: CGRect) {
super.init(frame: frame)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
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)
}
}