Skip to content

Instantly share code, notes, and snippets.

@prafullakumar
Created April 16, 2020 15:08
Show Gist options
  • Save prafullakumar/14aed6808a9a697cc7c1c57d018cfd9b to your computer and use it in GitHub Desktop.
Save prafullakumar/14aed6808a9a697cc7c1c57d018cfd9b to your computer and use it in GitHub Desktop.
Demo - Keyboard Animation with Form SwiftUI
import SwiftUI
import Combine
struct KeyboardProperty {
var currentHeight: CGFloat = 0
var animationDuration: Double = 0
//keyboard notification also gives UIKeyboardAnimationCurveUserInfoKey using which we can completly sync keyboard animation with Scrollview move but In SwiftUI I cannot find any way to use the same.
}
struct AdaptsKeyboard: ViewModifier {
@State var keyboardProperty: KeyboardProperty = KeyboardProperty()
func body(content: Content) -> some View {
content
.padding(.bottom, self.keyboardProperty.currentHeight)
.edgesIgnoringSafeArea(self.keyboardProperty.currentHeight == 0 ? Edge.Set() : .bottom)
.animation(self.keyboardProperty.currentHeight == 0 ?
.easeOut(duration: self.keyboardProperty.animationDuration) :
.easeIn(duration: self.keyboardProperty.animationDuration))
.onAppear(perform: subscribeToKeyboardEvents)
}
private let keyboardWillOpen = NotificationCenter.default
.publisher(for: UIResponder.keyboardWillShowNotification)
.map {
KeyboardProperty(currentHeight: ($0.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! CGRect).height,
animationDuration: ($0.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double))
}
private let keyboardWillHide = NotificationCenter.default
.publisher(for: UIResponder.keyboardWillHideNotification)
.map { KeyboardProperty(currentHeight: CGFloat.zero,
animationDuration: ($0.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double)) }
private func subscribeToKeyboardEvents() {
_ = Publishers.Merge(keyboardWillOpen, keyboardWillHide)
.subscribe(on: RunLoop.main)
.assign(to: \.self.keyboardProperty, on: self)
}
}
import SwiftUI
import Combine
struct KeyboardAwareScrollableView : View {
@State var street: String = ""
@State var city: String = ""
@State var country: String = ""
@State var postalCode: String = ""
var body: some View {
// Apply to any view with an instrinsic scroll view – ScrollView, Form, List, etc
Form {
Section(header: Text("Address")) {
TextField.init("street", text: $street)
TextField.init("city", text: $city)
TextField.init("country", text: $country)
TextField.init("postalCode", text: $postalCode)
}
Section(header: Text("Address")) {
TextField.init("street", text: $street)
TextField.init("city", text: $city)
TextField.init("country", text: $country)
TextField.init("postalCode", text: $postalCode)
}
Section(header: Text("Address")) {
TextField.init("street", text: $street)
TextField.init("city", text: $city)
TextField.init("country", text: $country)
TextField.init("postalCode", text: $postalCode)
}
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
KeyboardAwareScrollableView()
.navigationBarTitle("Keyboard Animation")
.modifier(AdaptsKeyboard())
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment