Skip to content

Instantly share code, notes, and snippets.

@fatbobman
Created May 13, 2024 03:49
Show Gist options
  • Save fatbobman/979368a26bb12bebbd6df20606d53944 to your computer and use it in GitHub Desktop.
Save fatbobman/979368a26bb12bebbd6df20606d53944 to your computer and use it in GitHub Desktop.
keyboardAvoiding for List
// by klaytonb
// https://forums.developer.apple.com/forums/thread/699111?answerId=740437022#740437022
import Combine
import SwiftUI
public extension Publishers {
static var keyboardHeight: AnyPublisher<CGFloat, Never> {
let willShow = NotificationCenter.default.publisher(for: UIApplication.keyboardWillShowNotification)
.map { $0.keyboardHeight }
let willHide = NotificationCenter.default.publisher(for: UIApplication.keyboardWillHideNotification)
.map { _ in CGFloat(0) }
return MergeMany(willShow, willHide)
.eraseToAnyPublisher()
}
}
public extension Notification {
var keyboardHeight: CGFloat {
return (userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height ?? 0
}
}
public struct KeyboardAvoiding: ViewModifier {
@State private var keyboardActiveAdjustment: CGFloat = 0
private let height: CGFloat
public init(height: CGFloat) {
self.height = height
}
public func body(content: Content) -> some View {
content
.safeAreaInset(edge: .bottom, spacing: keyboardActiveAdjustment) {
EmptyView().frame(height: 0)
}
.onReceive(Publishers.keyboardHeight) {
self.keyboardActiveAdjustment = min($0, height)
}
}
}
public extension View {
func keyboardAvoiding(height: CGFloat = 30) -> some View {
modifier(KeyboardAvoiding(height: height))
}
}
@smallstone719
Copy link

Hello, your method works very well with TextField. But with a TextEditor in a List or Form it doesn't seem to work as expected.

@fatbobman
Copy link
Author

@smallstone719 If you know the approximate height of TextEditor, you can adjust height through the height parameter
.keyboardAvoiding(height: 100)

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