Swift LayoutConstraint breaks on keyboard frame change - swift

I have a simple ViewController with a UITextView inside of a UIStackView. I've also stored an NSLayoutConstraint which is the bottom anchor of the stackView.
When the textView becomes first responder or resigns from first responder, two Notifications get triggered. The keyboardDidShowNotification works great. The issue is with keyboardWillHideNotification.
I’ve noticed that when I change the keyboard's frame by clicking the emojis button and then dismiss the keyboard, something breaks with the constraints.
As you can see in the gif below, as long as I don't go to the emojis section, the keyboard dismisses properly and the constraints are updated also properly. When I do go to the emojis section, then the bottomStackViewBottomConstraint and schoolTextViewTopConstraint go below that they should.
Here's what happens;
And here is the code;
fileprivate var schoolTextViewTopConstraint: NSLayoutConstraint!
fileprivate var bottomStackViewBottomConstraint: NSLayoutConstraint!
fileprivate func setupNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidShow), name: UIResponder.keyboardDidShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}
#objc fileprivate func keyboardDidShow(notification: Notification) {
if let infoKey = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey], let rawFrame = (infoKey as AnyObject).cgRectValue {
let keyboardFrame = self.view.convert(rawFrame, from: nil)
bottomStackViewBottomConstraint.constant = -(keyboardFrame.height) + self.view.safeAreaInsets.bottom
schoolTextViewTopConstraint.constant = -keyboardFrame.height + 180
}
UIView.animate(withDuration: 0, animations: {
self.sendCommentButton.isHidden = false
self.toggleMuteButton.isHidden = true
self.shareButton.isHidden = true
self.leaveRoomButton.isHidden = true
self.view.layoutIfNeeded()
}, completion: nil)
}
#objc fileprivate func keyboardWillHide(notification: Notification) {
schoolTextViewTopConstraint.constant = 0
bottomStackViewBottomConstraint.constant = 0
sendCommentButton.isHidden = true
UIView.animate(withDuration: 0.5, animations: {
self.toggleMuteButton.isHidden = self.currentUserRole == VoiceRoomRole.listener
self.shareButton.isHidden = false
self.leaveRoomButton.isHidden = false
self.view.layoutIfNeeded()
}, completion: nil)
}

Related

Swift - Dismiss Keyboard and call TouchUpInside Button Simultaneously not working when using UIKeyboardWillChangeFrame

I am using swift and having issues with TouchUpInside: if I'm using UIKeyboardWillChangeFrame or UIKeyboardWillShow/UIKeyboardWillHide, & the keyboard is showing, & the button I'm trying to press is behind the keyboard when keyboard is shown initially. (If I scroll down to the button till visible and press, no touchUpInside called).
TouchDown seems to work consistently whether the keyboard is showing or not, but TouchUpInside is not called. If the button is above the top of the keyboard when the keyboard is initially shown, TouchUpInside works. I'm using keyboardNotification to set the height of a view below my scrollView in order to raise up my scrollView when keyboard is showing. From what I can see it's only usually when the button is the last element in the scrollView (and therefore likely to be behind the keyboard when keyboard shown).
#IBOutlet var keyboardHeightLayoutConstraint: NSLayoutConstraint?
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var saveButton: UIButton!
#IBAction func saveTouchUpInside(_ sender: UIButton) {
print("touchupinside = does not work")
}
#objc func saveTouchDown(notification:NSNotification){
print("touchdown = works")
}
viewWillAppear:
textField.delegate = self
NotificationCenter.default.addObserver(self,selector:#selector(self.keyboardNotification(notification:)),name:
NSNotification.Name.UIKeyboardWillChangeFrame,object: nil)
self.saveButton.addTarget(self, action:#selector(ViewController.saveTouchDown(notification:)), for: .touchDown)
deinit {
NotificationCenter.default.removeObserver(self)
}
#objc func keyboardNotification(notification: NSNotification) {
if let userInfo = notification.userInfo {
let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let endFrameY = endFrame?.origin.y ?? 0
let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue
let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
if endFrameY >= UIScreen.main.bounds.size.height {
self.keyboardHeightLayoutConstraint?.constant = 0.0
} else {
self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0
}
UIView.animate(withDuration: duration, delay: TimeInterval(0),options: animationCurve, animations: { self.view.layoutIfNeeded() }, completion: nil)
}
}
I would like to dismiss the keyboard and call saveTouchUpInside at the same time, without using TouchDown.
I abstract the keyboard interaction as a separate class so that my controllers do not get bloated(also follows separation of concerns). Here is the keyboard manager class that I use.
import UIKit
/**
* To adjust the scroll view associated with the displayed view to accommodate
* the display of keyboard so that the view gets adjusted accordingly without getting hidden
*/
class KeyboardManager {
private var scrollView: UIScrollView
/**
* -parameter scrollView: ScrollView that need to be adjusted so that it does not get clipped by the presence of the keyboard
*/
init(scrollView: UIScrollView) {
self.scrollView = scrollView
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self,
selector: #selector(adjustForKeyboard),
name: UIResponder.keyboardWillHideNotification, object: nil)
notificationCenter.addObserver(self,
selector: #selector(adjustForKeyboard),
name: UIResponder.keyboardDidChangeFrameNotification, object: nil)
}
/**
* Indicates that the on-screen keyboard is about to be presented.
* -parameter notification: Contains animation and frame details on the keyboard
*
*/
#objc func adjustForKeyboard(notification: Notification) {
guard let containedView = scrollView.superview else { return }
let userInfo = notification.userInfo!
let keyboardScreenEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let keyboardViewEndFrame = containedView.convert(keyboardScreenEndFrame, to: containedView.window)
let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber
let rawAnimationCurveValue = (userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber).uintValue
UIView.animate(withDuration: TimeInterval(truncating: duration),
delay: 0,
options: [UIView.AnimationOptions(rawValue: rawAnimationCurveValue)],
animations: {
if notification.name == UIResponder.keyboardWillHideNotification {
self.scrollView.contentInset = UIEdgeInsets.zero
} else {
self.scrollView.contentInset = UIEdgeInsets(top: 0,
left: 0,
bottom: keyboardViewEndFrame.height,
right: 0)
}
self.scrollView.scrollIndicatorInsets = self.scrollView.contentInset
},
completion: nil)
}
deinit {
let notificationCenter = NotificationCenter.default
notificationCenter.removeObserver(self)
}
}
Its usage is like this
create a reference to the keyboard manager
private var keyboardManager: KeyboardManager!
and assign the keyboard manager class like below in viewDidLoad where self.scrollView is the scrollView that you are working with
self.keyboardManager = KeyboardManager(scrollView: self.scrollView)
This should take care of the issue. If that does not work, probably a sample project might help to take a deep dive into that.

KeyboardDidShow called when keyboard isn't shown

so I've set up keyboard observers using KeyboardDidShow so that I can shift the view up only when the keyboard is shown. However, KeyboardDidShow runs at the launch of every view and also at random times. I've tried monitoring the keyboard frames and only shifting the view if the frame changes, but every so often the view is still shifted even without the keyboard being shown. Usually, it happens whenever the view is first launched, so I tried adding a delay but it's not very dependable.
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidShow(_:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
}
#objc func keyboardDidShow(_ notification: Notification) {
let userInfo = notification.userInfo!
let beginFrameValue = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)!
let beginFrame = beginFrameValue.cgRectValue
let endFrameValue = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)!
let endFrame = endFrameValue.cgRectValue
if beginFrame.equalTo(endFrame) {
return
} else {
let indexPath = IndexPath(item: 0, section: 0)
if UIScreen.main.bounds.height == 812 {
collectionView?.contentInset = UIEdgeInsets(top: 318 + view.safeAreaInsets.bottom, left: 0, bottom: 73, right: 0)
}
collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)
}
}
The problem is that you have configured the wrong notification. Do not use UIKeyboardDidShow. Use UIKeyboardWillShow, and examine the old frame, the new frame, and whether the new frame will cover your view.
Arriving at a robust implementation is not trivial, but it is certainly a well established previously solved problem that has been explained here many times.
For UIViewController instances you need observer these notifications only when view is visible and not subscribe to notification multiple times. Best way to do so is:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardWillChangeFrame(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
And here is working code from my project to handle keayboard frame
#objc private func onKeyboardWillChangeFrame(_ notification: NSNotification) {
// extract values
if let userInfo = notification.userInfo,
let keyboardFrameEnd = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
let animationCurveInt = (userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber)?.intValue {
/*
СУКАБЛЯТЬ
With upgrate to Swift 4.2 UIView.AnimationCurve(rawValue: 7) returns actual instance of
UIView.AnimationCurve which crashes on access, mod by 4 limits value to max
*/
let animationCurve = UIView.AnimationCurve(rawValue: animationCurveInt % 4) ?? .easeIn
// View chanages
let topPoint = self.view.convert(keyboardFrameEnd.origin, from: self.view.window)
let height = self.view.bounds.size.height - topPoint.y
... update your constraints or manually update vars that affect layoutSubviews()...
let animationDuration: TimeInterval = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
var animationOptions: UIView.AnimationOptions = []
switch animationCurve {
case .easeInOut: animationOptions = .curveEaseInOut
case .easeIn: animationOptions = .curveEaseIn
case .easeOut: animationOptions = .curveEaseOut
case .linear: animationOptions = .curveLinear
}
// run animation
UIView.animate(withDuration: animationDuration, delay: 0, options: animationOptions, animations: {
self.view.layoutIfNeeded()
})
}
}

How do we make keyboard appear below textView in swift?

I have done keyboard appearing below textfield using
on View did Load adding a observer()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(Gold_Loan_First_ViewController.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(Gold_Loan_First_ViewController.keyboardWillBeHidden(_:)), name: UIKeyboardWillHideNotification, object: nil)
And then updating the frame
weak var activeField: UITextField?
func textFieldDidEndEditing(textField: UITextField) {
self.activeField = nil
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if textField==txtOTP {
txtOTP.errorMessage=""
}
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
self.activeField = textField
}
func keyboardDidShow(notification: NSNotification)
{
if let activeField = self.activeField,
let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect = self.view.frame
aRect.size.height -= keyboardSize.size.height
if (!CGRectContainsPoint(aRect, activeField.frame.origin)) {
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
func keyboardWillBeHidden(notification: NSNotification)
{
let contentInsets = UIEdgeInsetsZero
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
}
But how do I do it for a textView. I tried the same code with didBeginEditing of textView with no positive effect
One of the easy and no code of line solution is to use the following pods in your app.
IQKeyboardManger
Later you need to just import that in App Delegate and add this two lines of code in didfinishLaunching method:
IQKeyboardManager.sharedManager().enable = true
Your problem will be solved for whole app.
For Swift 5:
IQKeyboardManager.shared.enable = true
I have gone through such a situation. For this first I added extension in my UiViewController :
extension CCViewController : UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
// write code as per your requirements
}
func textViewDidEndEditing(_ textView: UITextView) {
// write code as per your requirements
}
func textViewDidChange(_ textView: UITextView) {
self.p_adjustMessageFieldFrameForTextView(textView)
}
}
// Defining the p_adjustMessageFieldFrameForTextView method
fileprivate func p_adjustMessageFieldFrameForTextView(_ textView : UITextView) {
var finalheight : CGFloat = textView.contentSize.height + 10
var kMaxMessageFieldHeight : CGFloat = 50
if (finalheight > kMaxMessageFieldHeight) {
finalheight = kMaxMessageFieldHeight;
} else if (finalheight < kCommentTextViewHeight){
finalheight = kCommentTextViewHeight;
}
scrollView!.view.frame = CGRect(x: 0, y: kNavBarHeight + statuBarHeight, width: SCREEN_WIDTH,height: SCREEN_HEIGHT - finalheight - keyboardRect!.size.height - kNavBarHeight - statuBarHeight)
// It is there for understanding that we have to calculate the exact frame of scroll view
commentTextView!.frame = CGRect(x: 0, y: bottomOfView(scrollView!.view), width: SCREEN_WIDTH, height: finalheight)
self.p_setContentOffsetWhenKeyboardIsVisible()
}
// Defining the p_setContentOffsetWhenKeyboardIsVisible method
fileprivate func p_setContentOffsetWhenKeyboardIsVisible() {
// here you can set the offset of your scroll view
}
Also there is a method named bottomView() :
func bottomOfView(_ view : UIView) -> CGFloat {
return view.frame.origin.y + view.frame.size.height
}
You can simply use TPKAScrollViewController.h & TPKAScrollViewController.m files by using Bridging Header.
While dragging these objective-C file to your swift project, it will automatically ask for Create Bridging. Create Bridging Header and Import #import "TPKAScrollViewController.h" to YourApp-Bridging-Header.h file.
After that, simply select your scrollView in XIB and change its class to TPKeyboardAvoidingScrollView as showing below.
Salman Ghumsani is Right.
Please change UIKeyboardFrameBeginUserInfoKey to UIKeyboardFrameEndUserInfoKey.
Apple Debeloper Document: Keyboard Notification User Info Keys
UIKeyboardFrameEndUserInfoKey
The key for an NSValue object containing a CGRect that identifies the ending frame rectangle of the keyboard in screen coordinates. The frame rectangle reflects the current orientation of the device.
UIKeyboardFrameBeginUserInfoKey
The key for an
NSValue
object containing a
CGRect
that identifies the starting frame rectangle of the keyboard in screen coordinates. The frame rectangle reflects the current orientation of the device.
Conclusion
So, if u use UIKeyboardFrameBeginUserInfoKey u might get the keyboard height to 0. Causing the system thought UITextView was not covered.
Find the correct height of keyboard and assign it to the bottom constraint of the textView or reduce the y position of textView.
Like:
Step-1:
make a property keyboardHeight in you viewController.
var keyboardHeight: CGFloat = 0.0
Step-2: Make #IBOutlet of bottom constraint of the textView.
#IBOutlet weak var textViewBottomConstraint: NSLayoutConstraint!
Step-3:
fileprivate func addKeyboardNotification() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
fileprivate func removeKeyboardNotification() {
IQKeyboardManager.shared().isEnabled = true
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
Copy & paste these functions to your view controllers, and call self.addKeyboardNotification() in viewDidLoad() and of you viewController
Step-4:
deinit {
self.removeKeyboardNotification()
}
also add this code to your viewController.
Step-5:
func keyboardWillShow(_ notification: Notification) {
if let keboardFrame = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue, self.keyboardHeight <= 0.0 {
self.keyboardHeight = keboardFrame.height + 45.0 //(Add 45 if your keyboard have toolBar if not then remove it)
}
UIView.animate(withDuration: 0.3, animations: {
self.textViewBottomConstraint.constant = self.keyboardHeight
}, completion: { (success) in
})
}
func keyboardWillHide(_ notification: Notification) {
UIView.animate(withDuration: 0.3, animations: {
self.textViewBottomConstraint.constant = 0.0
}, completion: { (success) in
})
}
That's it to manage the textView with keyboard.
If you don't want to use textViewBottomConstraint the you can work with the y position of the textView.

UITextview's contentInset & scrollIndicatorInsets with keyboard & rotation in Swift?

i'm using a UITextView and set it's contentInset & scrollIndicatorInsets when keyboard is show/hide like this:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardHide:", name: UIKeyboardWillHideNotification, object: nil)
}
override func shouldAutorotate() -> Bool {
return !self.keyboardShowing
}
func keyboardShow(n:NSNotification) {
self.keyboardShowing = true
let d = n.userInfo!
var r = (d[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
r = self.tv.convertRect(r, fromView:nil)
self.tv.contentInset.bottom = r.size.height
self.tv.scrollIndicatorInsets.bottom = r.size.height
}
func keyboardHide(n:NSNotification) {
self.keyboardShowing = false
self.tv.contentInset = UIEdgeInsetsZero
self.tv.scrollIndicatorInsets = UIEdgeInsetsZero
}
It works fine, but when I rotated my device, the scrollIndicatorInsets & contentInset didn't change with my new height. So what can I do? Thanks!
NOTE: The view has a Navigation bar on the top
Considering the UIKeyboardDidChangeFrameNotification notification. It's sent when the keyboard’s frame has just changed. Actually, you should use the UIKeyboardDidChangeFrameNotification instead of using UIKeyboardWillShowNotification.

How can I move the whole view up when the keyboard pop up? (Swift)

The gray box at the bottom is a text view. When I tap the text view, the keyboard will pop up from bottom. However, the text view has been covered by the pop up keyboard.
What functions should I add in order to move up the whole view when the keyboard pops up?
To detect when a keyboard shows up you could listen to the NSNotificationCenter
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: “keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
That will call keyboardWillShow and keyboardWillHide. Here you can do what you want with your UITextfield
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
//use keyboardSize.height to determine the height of the keyboard and set the height of your textfield accordingly
}
}
}
func keyboardWillHide(notification: NSNotification) {
//pull everything down again
}
As Milo says, to do this yourself you register for for keyboard show/hide notifications.
You then need to write code that figures out how much of the screen the keyboard is hiding, and how high on the screen the field in question is located, so you know how much to shift your views.
Once you've done that what you do depends on whether you're using AutoLayout or autoresizing masks (a.k.a. "Struts and springs" style layout.)
I wrote a developer blog post about a project that includes working code for shifting the keyboard. See this link:
http://wareto.com/animating-shapes-using-cashapelayer-and-cabasicanimation
In that post, look for the link titled "Sliding your views to make room for the keyboard" at the bottom.
Swift 4 complete solution.
I use this in all of my projects that need it.
on viewWillAppear register to listen for the keyboard showing/hiding and use the functions below to move the view up and back down.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
subscribeToKeyboardNotifications()
}
// stop listening for changes when view is dissappearing
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
unsubscribeFromKeyboardNotifications()
}
// listen for keyboard show/show events
func subscribeToKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: .UIKeyboardWillHide, object: nil)
}
func unsubscribeFromKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
#objc func keyboardWillHide(_ notification: Notification) {
view.frame.origin.y = 0
}
In my case I have a text field at the bottom which gets hidden by the keyboard so if this is in use then I move the view up
#objc func keyboardWillShow(_ notification: Notification) {
if bottomTextField.isFirstResponder {
view.frame.origin.y = -getKeyboardHeight(notification: notification)
}
}
func getKeyboardHeight(notification: Notification) -> CGFloat {
let userInfo = notification.userInfo
let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
return keyboardSize.cgRectValue.height
}
Swift 4
This code is not so perfect but worth a try!
First embed the whole view in a scrollView.
Add this little cute function to your class:
#objc func keyboardNotification(_ notification: Notification) {
if let userInfo = (notification as NSNotification).userInfo {
let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions().rawValue
let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
if (endFrame?.origin.y)! >= UIScreen.main.bounds.size.height {
scrollViewBottomConstraint?.constant = 0
} else {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight:Int = Int(keyboardSize.height)
scrollViewBottomConstraint?.constant = CGFloat(keyboardHeight)
scrollView.setContentOffset(CGPoint(x: 0, y: (scrollViewBottomConstraint?.constant)! / 2), animated: true)
}
}
UIView.animate(withDuration: duration, delay: TimeInterval(0), options: animationCurve, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
}
.
Add this one to your ViewDidLoad:
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardNotification(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
Don't forget to connect bottom constraint of your scrollView to your class (with name: "scrollViewBottomConstraint").