Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS AutoLayout with scrollview and keyboard

I have one view on my storyboard to show user log in form, so it looks like this: main view->scroll view->content view->two text fields and log in button at the top and one register button at the bottom of the view. I use autolayout and bottom button has bottom space constraint. When I tap on the text field and keyboard appears I would like to scroll view to change size to visible rect, but content size should remain to scroll down to the register button, but the button move up when the size of the scroll view change. How could I do what I want?

I use this code when keyboard appears:

- (void)keyboardWillShow:(NSNotification *)aNotification
{
    NSDictionary *info = [aNotification userInfo];
    NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [kbFrame CGRectValue];

    CGSize s = self.scrollView.contentSize;
    CGFloat height = keyboardFrame.size.height;
    self.scrollViewBottomLayoutConstraint.constant = height;

    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
        [self.scrollView setContentSize:s];
    }];
}
like image 409
Bartosz Bialecki Avatar asked Nov 01 '13 22:11

Bartosz Bialecki


2 Answers

The best way I have found is to override NSLayoutConstraint like so:

@implementation NHKeyboardLayoutConstraint

- (void) dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void) awakeFromNib {
    [super awakeFromNib];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillChangeFrame:)
                                                 name:UIKeyboardWillChangeFrameNotification
                                               object:nil];
}

- (void)keyboardWillChangeFrame:(NSNotification *)notification {

    CGRect endKBRect = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];

    CGFloat animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
    CGRect frame = [UIApplication sharedApplication].keyWindow.bounds;

    self.constant = frame.size.height - endKBRect.origin.y;


    [UIView animateWithDuration:animationDuration animations:^{
        [[UIApplication sharedApplication].keyWindow layoutIfNeeded];
    }];
}


@end

then in your xib change the class type of the offending constraint to this class.

like image 84
Nick Hingston Avatar answered Sep 27 '22 18:09

Nick Hingston


Try leaving the content size alone, and instead adjust the scroll view's contentInset property. Then you don't have to mess with constraints.

- (void)keyboardUp:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];
    CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

    UIEdgeInsets contentInset = self.scrollView.contentInset;
    contentInset.bottom = keyboardRect.size.height;
    self.scrollView.contentInset = contentInset;
}
like image 22
bilobatum Avatar answered Sep 27 '22 19:09

bilobatum