Skip to content

Instantly share code, notes, and snippets.

@sakiwei
Created June 26, 2024 22:58
Show Gist options
  • Save sakiwei/756c532db24706e3fb994b96541fa267 to your computer and use it in GitHub Desktop.
Save sakiwei/756c532db24706e3fb994b96541fa267 to your computer and use it in GitHub Desktop.
A super basic version of keyboard avoid logic in swiftui
import UIKit
import SwiftUI
import Combine
final class KeyboardObserver: ObservableObject {
@Published var keyboardHeight: CGFloat = 0
@Published var isVisible = false
var keyboardCancellable = Set<AnyCancellable>()
init() {
NotificationCenter.default
.publisher(for: UIWindow.keyboardWillShowNotification)
.sink { [weak self] notification in
guard let self else { return }
guard let userInfo = notification.userInfo else { return }
guard let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
self.isVisible = true
self.keyboardHeight = keyboardFrame.height
print("will show = \(userInfo)")
}
.store(in: &keyboardCancellable)
NotificationCenter.default
.publisher(for: UIWindow.keyboardWillHideNotification)
.sink { [weak self] notification in
guard let self else { return }
guard let userInfo = notification.userInfo else { return }
guard let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
self.isVisible = false
self.keyboardHeight = keyboardFrame.maxY >= UIScreen.main.bounds.maxY ? 0 : self.keyboardHeight
print("will hide = \(userInfo)")
}
.store(in: &keyboardCancellable)
}
}
extension View {
func avoidKeyboard() -> some View {
KeyboardAvoidView(content: self)
}
}
struct KeyboardAvoidView<Content: View>: View {
let content: Content
@StateObject var keyboardObserver = KeyboardObserver()
@State var animatedKeyboardHeight: CGFloat = 0
var body: some View {
content
.padding(.bottom, animatedKeyboardHeight)
.ignoresSafeArea(.all, edges: keyboardObserver.isVisible ? .bottom : [])
.onChange(of: keyboardObserver.keyboardHeight) { old, new in
withAnimation {
animatedKeyboardHeight = new
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment