Offset UITableView Content When Keyboard Appears

This post will show how to adjust the content insets of a uitableview or uitextview when the keyboard pops up, so nothing is hidden underneath. I’m just going to jump right into the code for this one because this post is more for reference whenever this topic comes up. I’m not going to do a full tutorial for something like this.

The way we will accomplish this is by first registering for keyboard notifications, then adjusting the content inset based on the height of the keyboard.

Register for notifications

In your viewDidLoad or viewWillAppear method add the code to register for keyboard notifications.

- (void)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];
}

We add this view controller as the observer. We pass in the selector of the method that should be called when this notification occurs, which we will write in a minute. Having the colon at the end of the selector is important because this tells it that it should pass the notification parameter to the method. Then we give the name of the notification we want to observe, UIKeyboardWillShowNotification and UIKeyboardWillHideNotification, which are predefined notifications. The object parameter is asking us to define which object will post this notification, which according to the documentation should be nil for the keyboard notifications.

Wherever you register for these notifications, you should unregister as an observer in the opposing method (viewDidAppear vs viewDidDisappear). So, if you put them in viewDidLoad, you can unregister in dealloc sinceviewDidUnload is deprecated.

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

This line simply removes this view controller as an observer of all notifications. Be sure not to call [super dealloc] now with ARC.

Apply the content insets

Now we need to write the keyboardWillShow: method we registered as the selector to call.

- (void)keyboardWillShow:(NSNotification *)notification
{    
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets;
    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);
    }

    self.tableView.contentInset = contentInsets;
    self.tableView.scrollIndicatorInsets = contentInsets;
    [self.tableView scrollToRowAtIndexPath:self.editingIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

To get the keyboard size, we first get the userInfo dictionary from the notification object, which stores any additional objects that our receiver might use. From that dictionary we can get the CGRect object describing the keyboard’s frame by using the key UIKeyboardFrameBeginUserInfoKey. Then we get the CGSize value from that CGRect.

The coordinates given to us do not take into account rotation, so we need to check if the app is in portrait or landscape mode. If we are in portrait we create a UIEdgeInsets object with the height of the keyboard. If in landscape we use the width since this is actually the height.

Next we apply the content inset to the tableview, or this could be a textview, scrollview, etc. This way is better than trying to change the frame of the view around to adjust. The tableview will stay in the same position, but it will move all of its content up above the keyboard.

Rotation is also handled this way because the UIKeyboardWillShowNotification is posted on an orientation change if the keyboard is open.

Restore original position

Now we just have to reset the inset when the keyboard hides.

- (void)keyboardWillHide:(NSNotification *)notification
{
    self.tableView.contentInset = UIEdgeInsetsZero;
    self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}

As pointed out by Alaeddine in the comments, you might want to wrap the setting of the insets in an animation. The usual keyboard animation rate seems to be 0.3 seconds, but it could be different based on region, such as when international users switch between keyboard sizes. The best way to get the duration of the animation is to grab it from the userInfo dictionary that comes in the keyboard notification. Be sure to make the change in both keyboardWillShow: andkeyboardWillHide:. The change that needs to be made is as follows…

NSNumber *rate = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];
[UIView animateWithDuration:rate.floatValue animations:^{
        self.tableView.contentInset = // insert content inset value here
        self.tableView.scrollIndicatorInsets = // insert content inset value here
}];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值