KeyboardAvoidanceSwiftUI
KeyboardAvoidanceSwiftUI copied to clipboard
Difference in behavior between iOS 13 and 14
The screenshot shows two simulators for iPhone 8: one running iOS 13.7 and the other 14.4. The code is identical between them, run from Xcode directly. I have verified the same behavior on a physical iOS 14 device.
In case it matters, the text field is actually hidden, and is in a ZStack
with the button on the bottom, to make sure it forces the button to move up above the keyboard. During normal operation, the keyboard is never hidden, though of course we can do so in the simulator.
For anyone that needs this: I figured out that iOS 14 automatically changes the size of a VStack
for the keyboard, making this modifier unnecessary.
I made the following change to KeyboardAdaptive.body(content:)
:
func body(content: Content) -> some View {
GeometryReader { (geometry) -> AnyView in
if #available(iOS 14, *) {
return AnyView(content)
}
return AnyView(content
.padding(.bottom, self.bottomPadding)
.onReceive(Publishers.keyboardHeight) { keyboardHeight in
let keyboardTop = geometry.frame(in: .global).height - keyboardHeight
let focusedTextInputBottom = UIResponder.currentFirstResponder?.globalFrame?.maxY ?? 0
self.bottomPadding = max(0, focusedTextInputBottom - keyboardTop - geometry.safeAreaInsets.bottom)
}
.animation(.easeOut(duration: 0.16))
)
}
}
Update for iOS 15:
content
.padding(.bottom, self.bottomPadding)
.onReceive(Publishers.keyboardHeight) { keyboardHeight in
let keyboardTop = geometry.frame(in: .global).height - min(0, keyboardHeight) // putting a floor on negative keyboard hight fixes a similar issue on iOS 15
let focusedTextInputBottom = UIResponder.currentFirstResponder?.globalFrame?.maxY ?? 0
self.bottomPadding = max(0, focusedTextInputBottom - keyboardTop)
}
.animation(.easeOut(duration: 0.25))
view is getting scrolled bit more..if the view is complex