Skip to content

Instantly share code, notes, and snippets.

@JamesSedlacek
Last active September 10, 2024 14:07
Show Gist options
  • Save JamesSedlacek/2d0425319e2a854da8c51f4b05c9842a to your computer and use it in GitHub Desktop.
Save JamesSedlacek/2d0425319e2a854da8c51f4b05c9842a to your computer and use it in GitHub Desktop.
SwiftUI Keyboard Toolbar Workaround
//
// KeyboardToolbar.swift
//
// Created by James Sedlacek on 9/20/23.
//
import SwiftUI
import Combine
@Observable
final class KeyboardToolbarViewModel {
var isKeyboardVisible = false
private var cancellables = Set<AnyCancellable>()
init() {
NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)
.sink { [weak self] _ in
withAnimation(.easeIn.delay(0.15)) {
self?.isKeyboardVisible = true
}
}
.store(in: &cancellables)
NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)
.sink { [weak self] _ in
self?.isKeyboardVisible = false
}
.store(in: &cancellables)
}
}
struct KeyboardToolbar<V: View>: ViewModifier {
@State private var viewModel: KeyboardToolbarViewModel = .init()
private let toolbar: V
init(@ViewBuilder toolbar: () -> V) {
self.toolbar = toolbar()
}
func body(content: Content) -> some View {
content
.safeAreaInset(edge: .bottom) {
if viewModel.isKeyboardVisible {
toolbar
}
}
}
}
extension View {
func keyboardToolbar<V: View>(view: @escaping () -> V) -> some View {
modifier(KeyboardToolbar(toolbar: view))
}
func keyboardDoneButton() -> some View {
modifier(KeyboardToolbar {
HStack {
Spacer()
Button("Done") {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
.padding(.horizontal)
}
.frame(height: 49)
.background(.bar)
})
}
}
@subelsky
Copy link

subelsky commented Jun 1, 2024

@JamesSedlacek thanks for this - it was the only fix I could get working!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment