Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I resize views when keyboard pops up using Auto Layout

I have a view (a UITableView in this case, but that's not important) on my UIViewController that I want to have the height resized when the keyboard pops up.

What is the best way to do this in Auto Layout? Currently on the view I have these constraints:

  • Top space to superview: 0
  • Trailing space to superview: 0
  • Leading space to superview: 0
  • Bottom space to superview: 0
  • Height equals = 424

I think the quickest way of doing this, is to remove the height and bottom space constraint and just resize the actual view in the code when keyboardDidAppear notification is called, but is there any other ways to do this?

EDIT: I removed the height constraint, my bad.

like image 822
Enrico Susatyo Avatar asked Jun 02 '14 06:06

Enrico Susatyo


2 Answers

I would give you a generic idea, it may need to be re-adjusted for your actual project.

swift 4.2

let notificationTokenKeyboardWillAppear = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { (note) in
    guard let keyboardFrame = (note.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
    UIView.animate(withDuration: CATransaction.animationDuration(), animations: {
        self.scrollView?.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardFrame.size.height, right: 0.0)
    }, completion: nil)
}

and

let notificationTokenKeyboardWillHide = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil) { (_) in
    UIView.animate(withDuration: CATransaction.animationDuration(), animations: {
        self.scrollView?.contentInset = .zero
    }, completion: nil)
}

NOTE-1: scrollView represents here any subset of UIScrollView, e.g. UITableView or UICollectionView, etc...

NOTE-2: you'll need to remove the tokens manually by invoking the removeObserver(_:) method when you are about to release the view and the closure-based observers are not necessary any longer


ObjC

I persume the UITableView *_tableView has been set up properly somewhere before.

- (void)viewDidLoad {

    // ...

    [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
        id _obj = [note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
        CGRect _keyboardFrame = CGRectNull;
        if ([_obj respondsToSelector:@selector(getValue:)]) [_obj getValue:&_keyboardFrame];
        [UIView animateWithDuration:0.25f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
            [_tableView setContentInset:UIEdgeInsetsMake(0.f, 0.f, _keyboardFrame.size.height, 0.f)];
        } completion:nil];
    }];
    
    [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillHideNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
        [UIView animateWithDuration:0.25f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
            [_tableView setContentInset:UIEdgeInsetsZero];
        } completion:nil];
     }];


     // ...

}

NOTE: if your UITableView is not at the bottom of the screen precisely, the contentInset value should be refined in this line: [_tableView setContentInset:UIEdgeInsetsMake(0.f, 0.f, _keyboardFrame.size.height, 0.f)];

like image 71
holex Avatar answered Nov 15 '22 21:11

holex


Keep your height constraint and connect an outlet to it:

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *CS_TableView_Height;

Take a look at Example 3 of this tutorial.

Update your view's height by capturing keyboard event using NSNotificationCenter:

- (void)viewWillAppear:(BOOL)animated
{
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

You might want to also take a look at the accepted answer of this question for some inspirations.

So in the end, you should get something like this:

- (void)keyboardWillShow
{

    self.CS_TableView_Height.constant = 500;//For example

    [self.tableView setNeedsUpdateConstraints];
}

- (void)keyboardWillHide
{

    self.CS_TableView_Height.constant = 568;// iPhone5 height

    [self.tableView setNeedsUpdateConstraints];
}
like image 22
Thanh-Nhon Nguyen Avatar answered Nov 15 '22 23:11

Thanh-Nhon Nguyen