I've been asking a question or two over the past few days of working on an application that keeps a custom toolbar aligned to the top of the iPhone keyboard. I'm using the method described by Josh in this question; basically, I have the view controller listen for the UIKeyboardWillShowNotification and add the toolbar as necessary.
The view controller itself manages a table view whose cells all contain a UITextField. The keyboard and toolbar being presented are editing these text fields. The only issue I'm still having is this: when the keyboard and toolbar are presented for a cell more than about halfway down the table, it scrolls to be visible above the keyboard, but not above the toolbar.
The cells and text fields are still editable, but about half the cell is hidden under the toolbar. If I disappear the toolbar (don't add it in the notification responder), the entire cell becomes visible, but obviously I lose the functionality the toolbar provides.
Is there a way to change the location the text field gets scrolled to? I've tried playing around with the UITableView method scrollToRowAtIndexPath:atScrollPosition:animated:
, but it tends to give weird results when toggling through several cells.
What's the best method for scrolling a table view cell to a visible position above a custom keyboard toolbar?
I do exactly what you are describing in my app. This is the code I use, verbatim. It's very nicely animated, and seems to work wonderfully.
Two disclaimers:
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
// adjust this following value to account for the height of your toolbar, too
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
- (void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect viewFrame = self.parentView.frame;
viewFrame.origin.y += animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.parentView setFrame:viewFrame];
[UIView commitAnimations];
}
- (void) textFieldDidBeginEditing:(UITextField*) textField {
CGRect textFieldRect = [self.parentView.window convertRect:textField.bounds fromView:textField];
CGRect viewRect = [self.parentView.window convertRect:self.parentView.bounds fromView:self.parentView];
CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator = midline - viewRect.origin.y - MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION) * viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction < 0.0) {
heightFraction = 0.0;
}else if (heightFraction > 1.0) {
heightFraction = 1.0;
}
animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
CGRect viewFrame = self.parentView.frame;
viewFrame.origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.parentView setFrame:viewFrame];
[UIView commitAnimations];
}
Assuming that you know the NSIndexPath that you would show above the keyboard, you can use the following fast and clean method:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
UITableViewCell *aCell = [myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:6 inSection:0]];
CGSize cellSize = aCell.frame.size;
[myTableView setContentOffset:CGPointMake(0, cellSize.height*6) animated:YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
[myTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
}
Since the UITableView inherits from UIScrollView you can adjust the contentOffset property to reflect the row visibility in which you are interested.
In the DidEndEditing method, you have to restore the original scroll position. This is achieved with a standard scrollToRowAtIndexPath:atScrollPosition:animated call.
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