У меня есть KeyboardObserver, который наблюдает за изменениями на клавиатуре и вычисляет необходимую высоту, чтобы настроить вид следующим образом:
final class KeyboardObserver: ObservableObject {
public var lastViewRect = CGRect()
@Published var keyboardMinY: CGFloat = 0 {
didSet {
if keyboardMinY == 0 {
lastViewAdjustment = 0
} else {
lastViewAdjustment = keyboardMinY - lastViewRect.maxY
}
}
}
@Published var lastViewAdjustment: CGFloat = 0
// keyboardWillShow notification may be posted repeatedly,
// this flag makes sure we only act once per keyboard appearance
@Published var keyboardIsHidden = true
func addObserver() {
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardDidHide(notification:)), name: UIResponder.keyboardDidHideNotification, object: nil)
}
func removeObserver() {
NotificationCenter.default.removeObserver(self)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc func keyBoardWillShow(notification: Notification) {
if keyboardIsHidden {
keyboardIsHidden = false
if let rect = notification.userInfo?["UIKeyboardFrameEndUserInfoKey"] as? CGRect {
keyboardMinY = rect.minY
}
}
}
@objc func keyBoardDidHide(notification: Notification) {
keyboardIsHidden = true
keyboardMinY = 0
}
}
Я использую его в представлении следующим образом:
struct SignUpView: View {
@ObservedObject private var keyboardObserver = KeyboardObserver()
var body: some View {
VStack(alignment: .leading) {
...
ScrollView {
IndicatorTextField("Full Name", .imageUserBlue, .turquoiseBlue)
.padding(.top, 48)
IndicatorTextField("Email Address", .imageEmail, .turquoiseBlue)
.padding(.top, 8)
IndicatorTextField("Home Town", .imageLocation, .turquoiseBlue)
.padding(.top, 8)
IndicatorTextField("Password", .imageLock, .reddishPink)
.padding(.top, 8)
IndicatorTextField("Date of Birth", .imageCalender, .reddishPink)
.padding(.top, 8)
IndicatorTextField("Gender", .imageUserRed, .reddishPink)
.padding(.top, 8)
Spacer()
.frame(width: 0, height: -keyboardObserver.lastViewAdjustment)
.animation(.linear(duration: 1))
}
.background(GeometryGetter(rect: $keyboardObserver.lastViewRect))
...
}
.background(BackgroundImage(.imageBgSignup))
.edgesIgnoringSafeArea(.all)
.onAppear { self.keyboardObserver.addObserver() }
.onDisappear { self.keyboardObserver.removeObserver() }
}
}
IndicatorTextField настроен только для TextField.
Я хочу добавить анимацию на клавиатуре, то есть, когда Spacer имеет высоту 135, которая скоро изменится на 0. Она быстро изменилась без анимации.
Я также пробовал обернуть Spacer блоком withAnimation
, но без плодотворного результата.
Есть предложения?