I want to move the screen upwards when I show the keyboard and move to the bottom when I hide the keyboard.
I use this code:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0{
self.view.frame.origin.y -= keyboardSize.height
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
self.view.frame.origin.y += keyboardSize.height
}
}
}
But I have this problem: http://gph.is/2AvLo1A
On this screen I tap on textField to show keyboard and tap on empty space to hide keyboard several times. My screen crawls down, and the black background fills the entire screen. How to fix it?
Update:
http://gph.is/2F7nux5
After shown the keyboard I have new empty space at the bottom. And if I scroll I can see it: https://imgur.com/a/fFyEC
Hook the bottom constraint of the scrollview to the superViews's bottom and drag it as IBOutlet and do this
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
self.scrollviewBottomCon.constant = keyboardSize.height
self.view.layoutIfNeeded()
self.scrollView.scrollRectToVisible((self.textfeild.frame), animated: true)
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
self.scrollviewBottomCon.constant = 0
self.view.layoutIfNeeded()
}
}
Try not to move the entire view up and down, rather the components you really need to move. I'd suggest using a view to contain the elements you want to move.
I have a use case where I have a coupe text fields and a submit button beneath in a container view. When the keyboard appears, I wanted the two text fields and button to rise. Here's how I handled that.
#objc func keyboardWillAppear(_ notification: NSNotification) {
if let userInfo = notification.userInfo,
let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
// Calculate how much to move
let submitButtonHeight = self.submitButton.frame.size.height
var submitButtonOrigin = self.view.convert(self.submitButton.frame.origin, from: self.containerView)
submitButtonOrigin.y = submitButtonOrigin.y + submitButtonHeight + 4.0
var visibleRect = self.view.frame
visibleRect.size.height -= keyboardFrame.height
// If keyboard covers the button, move the container up
if !visibleRect.contains(submitButtonOrigin) {
let keyboardMove = submitButtonOrigin.y - visibleRect.size.height
if keyboardMove > 0 {
UIView.animate(withDuration: 0.3) {
self.containerView.transform = CGAffineTransform(translationX: 0, y: -keyboardMove)
}
}
}
}
}
#objc func keyboardWillDisappear(_ notification: NSNotification) {
UIView.animate(withDuration: 0.3) {
self.containerView.transform = CGAffineTransform.identity
}
}
This may or may not be a solution for you, but can provide another option.
Related
i'm trying to show a button above keyboard when it is enable but it isn't working fine, when keyboard get open button doesn't move above keyboard and when i hide keyboard it move at the top of screen, How i can show button just above keyboard when it is shown to user. This is my code for showing button,
NotificationCenter.default.addObserver(self, selector: #selector(SignUpVC.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(SignUpVC.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.nextBtn.frame.origin.y == 0 {
self.nextBtn.frame.origin.y -= keyboardSize.height //can adjust as keyboardSize.height-(any number 30 or 40)
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if self.nextBtn.frame.origin.y != 0 {
self.nextBtn.frame.origin.y = 0
}
}
Button frame has an initial y value that isn't 0 , so you need to perserve it and set back
Option 1 : save button frame and restore it
var btnFrame:CGRect!
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
btnFrame = self.nextBtn.frame
self.nextBtn.frame.origin.y -= keyboardSize.height //can adjust as keyboardSize.height-(any number 30 or 40)
}
}
#objc func keyboardWillHide(notification: NSNotification) {
self.nextBtn.frame = btnFrame
}
Option 2 : move the view itself
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height //can adjust as keyboardSize.height-(any number 30 or 40)
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}
Replace UIKeyboardFrameBeginUserInfoKey with UIKeyboardFrameEndUserInfoKey
as a matter of fact you should change the frame of your view instead of changing button's frame. Place your button below the view and when keyboard pops up change push view upward.
I use code below to move screen up and down when keyboard show and hide
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector:#selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0{
self.view.frame.origin.y -= keyboardSize.height
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
self.view.frame.origin.y += keyboardSize.height
}
}
}
It works in all devices except iPhone x (I think the problem is iPhone X bottom wasted space)
Problem is that keyboard size change before shown and after that and cause the view go down and down and down...
Can anyone help?
You should also consider safe area insets
let endFrame = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue ?? CGRect.zero
let bottomSpace = keyboardValues.endFrame.maxY - keyboardValues.endFrame.minY - self.view.safeAreaInsets.bottom
And you should not be additive. These notifications may be posted multiple times. Use absolute values.
Here it is,
Use IQKeyboardManagerSwift
AppDelegate.swift settings
IQKeyboardManager.shared.enable = true
IQKeyboardManager.shared.enableAutoToolbar = false
In My ViewController
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
print(#function)
if DeviceType.checkiPhoneX() {
IQKeyboardManager.shared.keyboardDistanceFromTextField = 40.0
}
return true
}
func textViewDidEndEditing(_ textView: UITextView) {
if DeviceType.checkiPhoneX() {
IQKeyboardManager.shared.keyboardDistanceFromTextField = 0.0
}
}
This is how i manage Keyboard for X.
Hope this may help you.
Use UIKeyboardFrameEndUserInfoKey instead of UIKeyboardFrameBeginUserInfoKey.
i try to create a Chat UI. Therefore i added a Tableview and a textfield below. If a user wants to type in the textfield, the whole view should go up and thats work fine. If the user ends typing and the keyboard should be hidden, the first time the view moves a bit lower and the seccond time it moves lower as well. It looks like the following screenshots:
is used the following code:
override func viewDidLoad() {
super.viewDidLoad()
self.myChat.separatorStyle = .none
getChatId()
myChat.allowsSelection = false;
newMessage.delegate = self
// Do any additional setup after loading the view.
NotificationCenter.default.addObserver(self, selector: #selector(ChatViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ChatViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0{
self.view.frame.origin.y -= keyboardSize.height
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
self.view.frame.origin.y += keyboardSize.height-1
}
}
}[![normally it should look like this][1]][1]
regards
Change this function with my change.
#objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
self.view.frame.origin.y = 0
}
}
}
I have general message view controller I am sending message using textfield but keyboard is covered the text fields. I can refer
Move view with keyboard using Swift
this link added some code but after that some portion shows black. how to avoid the screen black after sending the message
this is code
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(GenralMessageViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(GenralMessageViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
self.view.frame.origin.y += keyboardSize.height
}
}
}
Your code is just wrong. You have no business changing the frame of self.view. The main view of a view controller must be left in place where it is. Wrap your interface in a subview of the main view and move the subview (if you insist on using this approach to avoiding being covered by the keyboard).
Try changing your end y origin back to 0 instead of a calculated value.
#objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
self.view.frame.origin.y == 0
}
}
}
I have an iOS app with login screen(mobile and password). Let's imagine a case:
User tap the phone number text field and number keyboard appears, view is up with keyboard.
User fill phone number and tap password text field, keyboard changes from number layout yo standard.
User tap Return button on keyboard, and keyboard dismiss, view is down.
User tap phone number text field or password on more time for data correction
And at stage 4 the keyboard appear, BUT view is not up anymore, and when I tap return button on keyboard, the view drop even down with black line on top of screen. How I can fix that problem? in code I have this:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
and in viewDidLoad:
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)
and
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height/3
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y += keyboardSize.height/3
}
}
}
Try this
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height/3
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}
}
I would suggest you to use the IQKeyboardmanager.It will take care of these things automatically
GitHub link - IQKeyboardManger