Joseph Gill
Joseph Gill

Reputation: 1067

Unable to change UITableView Height Constraint When Keyboard Appears Using Autolayout

So, much like the Messages app, I have a UITableView that takes up most of the screen. Below the UITableView, I have a UIView that contains a UITextView and a UIButton. When the user clicks on the UITextView, the keyboard appears. I have successfully moved the UIView to the top of the keyboard (that is what my bottomConstraint outlet does), but I am struggling to move the UITableView as well.

Right now I have a height constraint on the UITableView that is set to 528. I have connected that constraint to an Outlet and here is my keyboardWillShow method.

- (void)keyboardWillShow:(NSNotification *)sender {

    NSDictionary *info = [sender userInfo];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect frame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGRect newFrame = [self.view convertRect:frame fromView:[[UIApplication sharedApplication] delegate].window];
    self.bottomConstraint.constant = newFrame.origin.y - CGRectGetHeight(self.view.frame);

    CGFloat height = CGRectGetHeight(self.view.frame) - self.composeTextView.frame.size.height - newFrame.origin.y;
    self.tableViewHeightConstraint.constant = height;

    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
    }];}

Here are screenshots of my constraints/storyboard.

Storyboard

^^view controller

UITableView Constraints

^^UITableView Constraints

UIView Constraints

^^UIView Constraints (View containing button + textview)

Here is my error:

Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) (

"<NSLayoutConstraint:0x174280320 V:[UITableView:0x135031c00(528)]>",

"<NSLayoutConstraint:0x17409ff40 V:[UIView:0x174184ac0(40)]>",

"<NSLayoutConstraint:0x1742807d0 V:|-(0)-[UITableView:0x135031c00]   (Names: '|':UIView:0x174184b90 )>",

"<NSLayoutConstraint:0x1742808c0 V:[UITableView:0x135031c00]-(0)-[UIView:0x174184ac0]>",

"<_UILayoutSupportConstraint:0x1740b9d40 V:[_UILayoutGuide:0x1741b3b00(0)]>",

"<_UILayoutSupportConstraint:0x1740b9ce0 _UILayoutGuide:0x1741b3b00.bottom == UIView:0x174184b90.bottom>",

"<NSLayoutConstraint:0x174280690 UIView:0x174184ac0.bottom == _UILayoutGuide:0x1741b3b00.top - 224>",

"<NSLayoutConstraint:0x174280dc0 'UIView-Encapsulated-Layout-Height' V:[UIView:0x174184b90(568)]>"

)

Will attempt to recover by breaking constraint

NSLayoutConstraint:0x174280320 V:[UITableView:0x135031c00(528)]

Upvotes: 1

Views: 1048

Answers (1)

Pablo Carrillo Alvarez
Pablo Carrillo Alvarez

Reputation: 1182

Something like this should work as you just need to set the height don't need to calculate new frames:

- (void)keyboardWillShow:(NSNotification *)sender {

NSDictionary *info = [sender userInfo];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];


CGFloat height = self.tableViewHeightConstraint.constant-keyboardFrame.size.height-self.composeTextView.frame.size.height;
self.tableViewHeightConstraint.constant = height;

[UIView animateWithDuration:animationDuration animations:^{
    [self.view layoutIfNeeded];
}];}

Also it seems like would be easier if you just set the bottom constraint of the tableView to be the top of the composeTextView instead of use a fixed height. that would work all the time.

Upvotes: 2

Related Questions