Created
June 26, 2024 22:58
-
-
Save sakiwei/756c532db24706e3fb994b96541fa267 to your computer and use it in GitHub Desktop.
A super basic version of keyboard avoid logic in swiftui
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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