Last active
June 14, 2022 18:27
-
-
Save Sjahriyar/916e93153a29dc602b45f29d39182352 to your computer and use it in GitHub Desktop.
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
class SomeClass: UIViewController | |
{ | |
var firstResponder: UIView? /// To handle textField position when keyboard is visible. | |
var isKeyboardVisible = false /// You can handle tap on view by checking if keyboard is visible. | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
/* | |
Register notifications for when keyboard appears/disappears | |
Note that we don't remove the observers if target iOS is iOS 9.0 or later | |
Apples Doc: | |
If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its dealloc method. | |
*/ | |
NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotification(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) | |
NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotification(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) | |
} | |
@objc | |
fileprivate func keyboardNotification(_ notification: Notification) { | |
self.isKeyboardVisible.toggle() | |
if notification.name == UIResponder.keyboardWillShowNotification { | |
guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return } | |
let keyboardFrame = keyboardValue.cgRectValue | |
// Note that textView delegate gets called later that keyboard notification unlike TextFields. | |
// So if firstResponder variable is nil it means our textView is firstRespnder. | |
if let textField = self.firstResponder ?? self.textView { | |
let textFieldPoints = textField.convert(textField.frame.origin, to: self.view.window) | |
let textFieldRect = textField.convert(textField.frame, to: self.view.window) | |
let contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardFrame.height + textField.frame.height, right: 0) | |
self.scrollView.contentInset = contentInset | |
self.scrollView.scrollIndicatorInsets = contentInset | |
// visible part of the view, where is not covered by the keyboard. | |
var windowFrame = self.view.frame | |
windowFrame.size.height -= keyboardFrame.height | |
// if you don't see the firstResponder view in visible part, means the view is beneth the keyboard. | |
if !windowFrame.contains(textFieldPoints) { | |
self.scrollView.scrollRectToVisible(textFieldRect, animated: true) | |
} | |
} | |
} | |
if notification.name == UIResponder.keyboardWillHideNotification { | |
self.scrollView.contentInset = .zero | |
self.scrollView.scrollIndicatorInsets = .zero | |
} | |
} | |
} | |
// MARK: Delegates | |
extension SomeClass: UITextFieldDelegate | |
{ | |
// MARK: TextField Delegate | |
func textFieldDidBeginEditing(_ textField: UITextField) { | |
self.firstResponder = textField // We set the firstResponder variable to active textField, | |
// This then will be handled in keyboardNotification() | |
} | |
func textFieldDidEndEditing(_ textField: UITextField) { | |
self.firstResponder = nil | |
} | |
func textFieldShouldReturn(_ textField: UITextField) -> Bool { | |
textField.resignFirstResponder() | |
return true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment