Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize the screen when keyboard appears

Tags:

I am building a chat app. I have to move a textfield when keyboard appears. I am doing this with the following code:

func keyboardWillShow(notification: NSNotification) {     if let userInfo = notification.userInfo {         if let keyboardSize =  (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {             kbHeight = keyboardSize.height             self.animateTextField(true)         }     } } func keyboardWillHide(notification: NSNotification) {     self.animateTextField(false) }  func animateTextField(up: Bool) {     var movement = (up ? -kbHeight : kbHeight)      UIView.animateWithDuration(0.3, animations: {         self.view.frame = CGRectOffset(self.view.frame, 0, movement)     }) } 

But when I use this code, the first messages doesn't show. I guess I have to resize the tableview.

Here are screenshots Before and After the keyboard appears:

I am using auto layout.

How can I resolve this problem?

like image 602
Okan Avatar asked Jun 07 '15 08:06

Okan


People also ask

When the keyboard appears the flutter widget resize How do you prevent this?

Steps to fix Flutter keyboard resize screen issue Step 1: Open the page where you have the TextField widget. Step 2: Locate the Scaffold widget. Step 3: Inside the Scaffold widget, add the resizeToAvoidBottomInset property and set its value to false . Step 4: Re-run the app.

How do you fix a keyboard overflow flutter?

The solution to resolve this overflow error is to make your entire widget or in our case the Column scrollable. We can do that by wrapping our Column inside a SingleChildScrollView. Also, wrap the SingleChildScrollView with Center so that the entire UI is centered.

How do I make my keyboard height flutter?

To know about the keyboard height, you can just check for the bottom property of viewInsets , when the keyboard is onscreen, this will hold the height of keyboard else zero. Note: The bottom property may have value even if some other system ui obscures the flutter ui from bottom. Hope that helps!

When should we use a resizeToAvoidBottomInset?

Use resizeToAvoidBottomInset to specify if the body should resize when the keyboard appears.


2 Answers

You can create an outlet of the bottom auto layout constraint of your table view.

Then simply use this code:

func keyboardWillShow(sender: NSNotification) {     let info = sender.userInfo!     var keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height     bottomConstraint.constant = keyboardSize - bottomLayoutGuide.length      let duration: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue      UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() } }  func keyboardWillHide(sender: NSNotification) {     let info = sender.userInfo!     let duration: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue     bottomConstraint.constant = 0      UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() } } 

If you have trouble creating the bottom constraint:

In storyboard

  • Select your search bar.
  • At the corner in the lower right you'll see 3 icons. Click the middle one looking like |-[]-|.
  • At the top of that popup, there are 4 boxes. Enter 0 at the one for the bottom.
  • Constraint created!

Now you can drag it to your view controller and add it as an outlet.

Another solution is to set the tableView.contentInset.bottom. But I haven't done that before. If you prefer that, I can try to explain it.

Using inset:

func keyboardWillShow(sender: NSNotification) {     let info = sender.userInfo!     let keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height      tableView.contentInset.bottom = keyboardSize }  func keyboardWillHide(sender: NSNotification) {     tableView.contentInset.bottom = 0 } 

You can try this code for setting the inset. I haven't tried it myself yet, but it should be something like that.

EDIT: Changed the duration with the advice of nacho4d

like image 186
Eendje Avatar answered Sep 28 '22 06:09

Eendje


2020 UPDATE

Correctly using a constraint...

There is only one way to properly handle this mess in iOS.

  1. Paste KUIViewController below in to your project,

  2. Create a constraint which is very simply to the "bottom of your content".

  3. Drag that constraint to bottomConstraintForKeyboard

KUIViewController will automatically and correctly resize your content view at all times.

Absolutely everything is totally automatic.

All Apple behaviors are handled correctly in the standard way, such as dismissing by taps, etc etc.

You are 100% completely done.

So "which view should you resize?"

You can not use .view ...

Because ... you cannot resize the .view in iOS!!!!!! Doh!

Simply make a UIView named "holder". It sits inside .view.

Put everything of yours inside "holder".

Holder will of course have four simple constraints top/bottom/left/right to .view.

That bottom constraint to "holder" is indeed bottomConstraintForKeyboard.

You're done.

Send a bill to the cliient and go drinking.

There is nothing more to do.

class KUIViewController: UIViewController {      // KBaseVC is the KEYBOARD variant BaseVC. more on this later      @IBOutlet var bottomConstraintForKeyboard: NSLayoutConstraint!      @objc func keyboardWillShow(sender: NSNotification) {         let i = sender.userInfo!         let s: TimeInterval = (i[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue         let k = (i[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height         bottomConstraintForKeyboard.constant = k         // Note. that is the correct, actual value. Some prefer to use:         // bottomConstraintForKeyboard.constant = k - bottomLayoutGuide.length         UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }     }      @objc func keyboardWillHide(sender: NSNotification) {         let info = sender.userInfo!         let s: TimeInterval = (info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue         bottomConstraintForKeyboard.constant = 0         UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }     }      @objc func clearKeyboard() {         view.endEditing(true)         // (subtle iOS bug/problem in obscure cases: see note below         // you may prefer to add a short delay here)     }      func keyboardNotifications() {         NotificationCenter.default.addObserver(self,             selector: #selector(keyboardWillShow),             name: UIResponder.keyboardWillShowNotification,             object: nil)         NotificationCenter.default.addObserver(self,             selector: #selector(keyboardWillHide),             name: UIResponder.keyboardWillHideNotification,             object: nil)     }      override func viewDidLoad() {         super.viewDidLoad()         keyboardNotifications()         let t = UITapGestureRecognizer(target: self, action: #selector(clearKeyboard))         view.addGestureRecognizer(t)         t.cancelsTouchesInView = false     } } 

Simply ...

Use KUIViewController anywhere a keyboard might appear.

class AddCustomer: KUIViewController, SomeProtocol {  class EnterPost: KUIViewController {  class EditPurchase: KUIViewController { 

On those screens absolutely everything is now completely automatic regarding the keyboard.

You're done.

Phew.


*Minor footnote - background clicks correctly dismiss the keyboard. That includes clicks which fall on your content. This is correct Apple behavior. Any unusual variation from that would take a huge amount of very anti-Apple custom programming.

*Extremely minor footnote - so, any and all buttons on the screen will work 100% correctly every time. However in the INCREDIBLY obscure case of nested (!) container views inside nested (!) scroll views with nested (!) page view containers (!!!!), you may find that a button will seemingly not work. This seems to be basically a (obscure!) problem in current iOS. If you encounter this incredibly obscure problem, fortunately the solution is simple. Looking at the function clearKeyboard(), simply add a short delay, you're done.

@objc func clearKeyboard() {     DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {         self.view.endEditing(true)     } } 

(A great tip from user @wildcat12 https://stackoverflow.com/a/57698468/294884 )

like image 26
Fattie Avatar answered Sep 28 '22 08:09

Fattie