Move screen up when keyboard appears in iPhone X - ios

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.

Related

Issue while showing button on above keyboard when enable in swift

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.

Swift Table View (Chat UI) if keyboard was shown, whole view getting lower

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
}
}
}

screen is black when move view in swift4

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
}
}
}

Move the screen with keyboard

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.

How can I get the keyboard size without getting an error?

I have a text view that sits at the bottom of my screen, and would like to push it up when users start editing the text view. I know how to push the view upwards, but because of different screen sizes the display isn't always the same. I'd like to get the height of the keyboard so that the text view sits just above it when a user edits. I have a piece of code below, yet when I add the following 3 lines, the app fails to build and gives me an error. Without this piece of code, the app runs perfectly. The error I get is "swift compiler error: expected declaration". These lines go into my keyboardWillShow function.
if let userInfo = sender.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
keyboardHeight = keyboardSize.height
}
So the full code looks like this.
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}
var isShown: Bool = false
var willHide: Bool = false
var keyboardHeight: CGFloat = 0
func keyboardWillShow(sender: NSNotification) {
isShown = true
//The following 3 lines seem to be the problem. Somehow the code stops working when I add them.
if let userInfo = sender.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
keyboardHeight = keyboardSize.height
}
}
func keyboardWillHide(sender: NSNotification) {
willHide = true
}
func textViewDidBeginEditing(textView: UITextView) {
if isShown == true {
self.view.frame.origin.y -= keyboardHeight
}
}
func textViewDidEndEditing(textView: UITextView) {
if willHide == true {
self.view.frame.origin.y += keyboardHeight
}
}

Resources