I have a UITableView
that is slightly larger than self.view
. I have a UITextField
at the bottom of the view, and I use the delegate method – textFieldDidBeginEditing:
to move the view up when the text field starts editing.
This works fine, but if I attempt to scroll the view while the UITextField
is being edited (and the content is already offset) then the content jerks to the bottom 'appropriate' position for the view. Put another way, the contentOffset.y
I set is changed to be equal to the size of the content view (as you would expect for normal behaviour).
Any ideas how to over-ride this behaviour while editing?
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
// Scroll to the currently editing text field
[self scrollViewToTextField:textField];
}
- (void)scrollViewToTextField:(id)textField
{
// Set the current _scrollOffset, so we can return the user after editing
_scrollOffsetY = self.tableView.contentOffset.y;
// Get a pointer to the text field's cell
UITableViewCell *theTextFieldCell = (UITableViewCell *)[textField superview];
// Get the text fields location
CGPoint point = [theTextFieldCell convertPoint:theTextFieldCell.frame.origin toView:self.tableView];
// Scroll to cell
[self.tableView setContentOffset:CGPointMake(0, point.y - 12) animated: YES];
}
The way to avoid this behaviour is to apply contentInset
at the same time. So for the above example:
- (void)scrollViewToTextField:(id)textField
{
// Set the current _scrollOffset, so we can return the user after editing
_scrollOffsetY = self.tableView.contentOffset.y;
// Get a pointer to the text field's cell
UITableViewCell *theTextFieldCell = (UITableViewCell *)[textField superview];
// Get the text fields location
CGPoint point = [theTextFieldCell convertPoint:theTextFieldCell.frame.origin toView:self.tableView];
// Scroll to cell
[self.tableView setContentOffset:CGPointMake(0, point.y - 12) animated: YES];
// Add some padding at the bottom to 'trick' the scrollView.
[self.tableView setContentInset:UIEdgeInsetsMake(0, 0, point.y - 60, 0)];
}
Then be sure to reset the inset after editing:
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self.tableView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
}
The caveat of this approach is that you'll have to implement some checking in the - (void)scrollViewDidScroll:(UIScrollView *)scrollView
method to check that your text field is still in view.
The alternative to this is to disable scrolling when editing begins, and reenable scrolling as it ends. You'll have to decide whether this action is bad for UX in your application.
I would like to add that if you are using input textfields. And need to scroll then apply a firstResponder that applying an EdgeInset using:
[self.tableView setContentOffset:CGPointMake(0.0f, 0.0f) animated:YES];
[self.tableView setContentInset:UIEdgeInsetsZero];
After stops the auto scroll that happens with input fields within UITableView when they get focus. Thanks @squarefrog
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With