Swift 4.2 Make Bottom of Tableview Move Up When Keyboard Shows

Swift 4.2 Make bottom of tableView move up when keyboard shows

One solution (which I sometimes use) is simply change the content offset of the tableView when the keyboard appears/disappears. I believe this would work in your instance as opposed to varying the tableView's constraints as you mentioned your UIViewController is a UITableViewController. Please see the below code for my suggestion, hope this helps!

Handle Notifications:

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)

NotificationCenter.default.addObserver(self, selector: #selector(EntryViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(EntryViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

NotificationCenter.default.removeObserver(self)
}

Actions:

@objc func keyboardWillShow(notification: Notification) {
if let keyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
print("Notification: Keyboard will show")
tableView.setBottomInset(to: keyboardHeight)
}
}

@objc func keyboardWillHide(notification: Notification) {
print("Notification: Keyboard will hide")
tableView.setBottomInset(to: 0.0)
}

Extensions:

extension UITableView {

func setBottomInset(to value: CGFloat) {
let edgeInset = UIEdgeInsets(top: 0, left: 0, bottom: value, right: 0)

self.contentInset = edgeInset
self.scrollIndicatorInsets = edgeInset
}
}

Tableview scroll content when keyboard shows

Try keeping the editing index path editingIndexPath Getting index path and scroll tableview to that index path

func keyboardWasShown (notification: NSNotification)
{
println("keyboard was shown")
var info = notification.userInfo
var keyboardSize = info.objectForKey(UIKeyboardFrameBeginUserInfoKey).CGRectValue().size

var contentInsets:UIEdgeInsets

if UIInterfaceOrientationIsPortrait(UIApplication.sharedApplication().statusBarOrientation) {

contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
}
else {
contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.width, 0.0);

}

myTableView.contentInset = contentInsets

myTableView.scrollToRowAtIndexPath(editingIndexPath, atScrollPosition: .Top, animated: true)
myTableView.scrollIndicatorInsets = myTableView.contentInset
}

Keep Bottom of TableView Visible When Keyboard Shows With Autolayout in Swift

One approach:

  • constrain the top of the tableView to the top of the view
  • constrain the bottom of the tableView to the top of the textField
  • constrain the bottom of the textField to the bottom of the view
  • create an @IBOutlet for the textField's bottom constraint

When the keyboard is shown, change the .constant of the textField's bottom constraint to the height of the keyboard view.

This will move the textField up, and because it's top is constrained to the bottom of the tableView, it will also move the tableView's bottom edge up.

Then scroll to the bottom of the tableView.

Layout:

Sample Image

Initial hierarchy, with 20 rows (scrolled to the bottom):

Sample Image

Hierarchy view (tableView background color set to green, so we can see its frame):

Sample Image

View after the keyboard is shown:

Sample Image

Hierarchy after the keyboard is shown:

Sample Image

Little tough to see from static screen caps, but the frame of the green rectangle (the tableView background) is now shorter... the user can still scroll up and down to see all the rows, but the bottom of the tableView is still constrained to the top of the textField.

When you the keyboard is dismissed, set the .constant of the textField's bottom constraint back to Zero.

You can see a full, working example project up on GitHub: https://github.com/DonMag/KBAdjust

Move view with keyboard using Swift

Here is a solution, without handling the switch from one textField to another:

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

func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.origin.y -= keyboardSize.height
}
}

func keyboardWillHide(notification: NSNotification) {
self.view.frame.origin.y = 0
}

To solve this, replace the two functions keyboardWillShow/Hide with these:

func keyboardWillShow(notification: NSNotification) {        
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
if view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height
}
}
}

func keyboardWillHide(notification: NSNotification) {
if view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}

Swift 3.0:

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?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height
}
}
}

@objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}

Swift 4.0:

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?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height
}
}
}

@objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}

Swift 4.2:

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height
}
}
}

@objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}

How to move tableview up when some particular textfield are hidden by keyboard?

Use IQKeyboardManager with just single line of code in appdelegate.It will take care of keyboard.

step 1) Add pod 'IQKeyboardManager' in pod-file and run pod install

step 2) Enable IQKeyboardManager by writing this piece of code in didFinishLaunchingWithOptions method of appdelegate

IQKeyboardManager.shared.enable = true

Refrence: https://github.com/hackiftekhar/IQKeyboardManager

Move textfield when keyboard appears swift

There are a couple of improvements to be made on the existing answers.

Firstly the UIKeyboardWillChangeFrameNotification is probably the best notification as it handles changes that aren't just show/hide but changes due to keyboard changes (language, using 3rd party keyboards etc.) and rotations too (but note comment below indicating the keyboard will hide should also be handled to support hardware keyboard connection).

Secondly the animation parameters can be pulled from the notification to ensure that animations are properly together.

There are probably options to clean up this code a bit more especially if you are comfortable with force unwrapping the dictionary code.

 class MyViewController: UIViewController {

// This constraint ties an element at zero points from the bottom layout guide
@IBOutlet var keyboardHeightLayoutConstraint: NSLayoutConstraint?

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardNotification(notification:)),
name: UIResponder.keyboardWillChangeFrameNotification,
object: nil)
}

deinit {
NotificationCenter.default.removeObserver(self)
}

@objc func keyboardNotification(notification: NSNotification) {
guard let userInfo = notification.userInfo else { return }

let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let endFrameY = endFrame?.origin.y ?? 0
let duration:TimeInterval = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(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)
}
}

Move a view up only when the keyboard covers an input field

Your problem is well explained in this document by Apple. Example code on this page (at Listing 4-1) does exactly what you need, it will scroll your view only when the current editing should be under the keyboard. You only need to put your needed controls in a scrollViiew.
The only problem is that this is Objective-C and I think you need it in Swift..so..here it is:

Declare a variable

var activeField: UITextField?

then add these methods

 func registerForKeyboardNotifications()
{
//Adding notifies on keyboard appearing
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}

func deregisterFromKeyboardNotifications()
{
//Removing notifies on keyboard appearing
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(notification: NSNotification)
{
//Need to calculate keyboard exact size due to Apple suggestions
self.scrollView.scrollEnabled = true
var info : NSDictionary = notification.userInfo!
var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets

var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeFieldPresent = activeField
{
if (!CGRectContainsPoint(aRect, activeField!.frame.origin))
{
self.scrollView.scrollRectToVisible(activeField!.frame, animated: true)
}
}

}

func keyboardWillBeHidden(notification: NSNotification)
{
//Once keyboard disappears, restore original positions
var info : NSDictionary = notification.userInfo!
var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
self.scrollView.scrollEnabled = false

}

func textFieldDidBeginEditing(textField: UITextField!)
{
activeField = textField
}

func textFieldDidEndEditing(textField: UITextField!)
{
activeField = nil
}

Be sure to declare your ViewController as UITextFieldDelegate and set correct delegates in your initialization methods:
ex:

self.you_text_field.delegate = self

And remember to call registerForKeyboardNotifications on viewInit and deregisterFromKeyboardNotifications on exit.

Edit/Update: Swift 4.2 Syntax

func registerForKeyboardNotifications(){
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

func deregisterFromKeyboardNotifications(){
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWasShown(notification: NSNotification){
//Need to calculate keyboard exact size due to Apple suggestions
self.scrollView.isScrollEnabled = true
var info = notification.userInfo!
let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 0.0)

self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets

var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.activeField {
if (!aRect.contains(activeField.frame.origin)){
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}

@objc func keyboardWillBeHidden(notification: NSNotification){
//Once keyboard disappears, restore original positions
var info = notification.userInfo!
let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
self.scrollView.isScrollEnabled = false
}

func textFieldDidBeginEditing(_ textField: UITextField){
activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
activeField = nil
}

moving View up with textfield and Button when keyboard appear Swift

Here is solution, Create bottom layout constraint reference of send button view

@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
@IBOutlet weak var sendbuttonView: UIView!

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self)
}

@objc func handleKeyboardNotification(_ notification: Notification) {

if let userInfo = notification.userInfo {

let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue

let isKeyboardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow

bottomConstraint?.constant = isKeyboardShowing ? -keyboardFrame!.height : 0

UIView.animate(withDuration: 0.5, animations: { () -> Void in
self.view.layoutIfNeeded()
})
}
}

Demo example

Scroll UITextField above Keyboard in a UITableViewCell on a regular UIViewController

I spent all day trying to figure this out. I posted it here, then found a blog link and an incredibly simple solution. It looks like this:

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
CGPoint pointInTable = [textField.superview convertPoint:textField.frame.origin toView:self.tableView];
CGPoint contentOffset = self.tableView.contentOffset;

contentOffset.y = (pointInTable.y - textField.inputAccessoryView.frame.size.height);

NSLog(@"contentOffset is: %@", NSStringFromCGPoint(contentOffset));

[self.tableView setContentOffset:contentOffset animated:YES];

return YES;
}

-(BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];

if ([textField.superview.superview isKindOfClass:[UITableViewCell class]])
{
UITableViewCell *cell = (UITableViewCell*)textField.superview.superview;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:TRUE];
}

return YES;
}

Check this for iOS 8



Related Topics



Leave a reply



Submit