views:

114

answers:

2

Hi.

I have a table with several text fields in it. Tapping on any of the text fields brings up the keyboard and the view scrolls automatically to bring the cursor above the keyboard if required.

I have a method in there that gets called whenever the user presses the Return key while editing a text field and I simply move the first responder status to the next text field in that. However, if it happens to be behind the keyboard, it does not scroll up and reveal itself.

I know this involves using the ‘beginAnimations’ method of ‘UIView’ and changing the position or size of the view but I don’t know how to calculate how much the view should move, etc.? Is there an easy way to do this? I don’t think Apple has explained this in the documentation and I’ve already tried Googling, but couldn’t come up with a decent solution.

Any help would be greatly appreciated.

Thank you.

A: 

AFAIK there is indeed no developer friendly way to do this. Copy&pasting from another project, this is what I came up with:

-(void)scrollViewToCenter:(UIView*)v
{
    CGFloat windowLeft = 200.0f;
    CGFloat y = v.frame.origin.y-(windowLeft - v.frame.size.height)/2;
    if ( y > scrollView.contentSize.height - windowLeft )
    {
        y = scrollView.contentSize.height - windowLeft;
    }
    if ( y < 0.0f ) y = 0.0f;
    [scrollView setContentOffset:CGPointMake(0.0f,y) animated:YES];
}

windowleft is the number of px left when the keyboard comes out. This assumes you have a UIScrollView called scrollView.

And then just call

[self scrollViewToCenter:tf];

edit: Note: for this to work, the UIView passed should preferably be a subview of the scrollView.

mvds
The table is not in a scroll view, so I’m not sure how I would adapt that bit of code to fit my needs. Thank you for the quick reply though. Given the sheer breadth of APIs available in the iPhone SDK, it’s amazing that something so common requires so much effort to achieve.
aryayush
ok, looked at your screenshot and it's a `UITableView`, didn't get that at first. `UITableView` inherits from `UIScrollView`, so I presume you can just go ahead and `setContentOffset` on it; i.e. replace `scrollView` with `tableView` if you like. But please check if `tableView.contentSize.height` has the expected value. The table cell you are positioning can than be passed as the `UIView`.
mvds
Thanks a bunch! I’ll say right out of the gate that I don’t have a very good understanding of how to do these point-based calculations to determine which view should move to where, so I do not really understand what exactly is happening in this bit of code. I did, however, set some breakpoints and determine that ‘y’ was always ending up in the negative in my app, so I changed the ‘if’ condition thusly: “if (y < 0.0f) y = 200.0f;”. And it’s working now. So thank you. I will have to understand the workings of this somehow though…
aryayush
the calculations are quite simple, but you always have to remember that they are relative to the container of the view. E.g. the main `UIView` is positioned relative to the window, `UITableView` is positioned relative to the `UIView`, `UITableViewCell` is positioned relative to the `UITableView`.
mvds
I found a method that fixed my problem and I now have a much better understanding of how this works (and a more streamlined code). Posting it as an answer here. Once again, thanks for your help. It would’ve taken me a lot of time to figure it out otherwise.
aryayush
A: 

Found a solution to this, thanks to ‘mvds’ here and some digging around in the documentation. This is what my revised ‘scrollViewToCenter’ method looks like:

- (void)scrollViewToCenter
{
    [self determineActiveTextField];
    CGPoint textFieldOrigin = [activeTextField convertPoint:activeTextField.frame.origin toView:self.view];
    CGFloat scrollPoint = self.view.frame.size.height / 2 - activeTextField.frame.size.height;
    if (textFieldOrigin.y > scrollPoint) {
        CGFloat scrollDistance = textFieldOrigin.y - scrollPoint;
        [self.tableView setContentOffset:CGPointMake(0.0f,scrollDistance) animated:YES];
    }
}

I call it whenever the user taps into any of the text fields (or it has been made the first responder programmatically) by adding it as a selector for the ‘UITextFieldTextDidBeginEditingNotification’ notification thusly:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollViewToCenter) name:UITextFieldTextDidBeginEditingNotification object:textField];

When the method is called, it first determines which of the seven text fields is the active one and then, using the ‘convertPoint:toView:’ method, converts its origin point to a point on ‘self.view’. Once I have the point where the text field originates from, I calculate if it is below the halfway point on the screen and, if so, offset the table view accordingly using the ‘setContentOffset’ method.

I’ve posted this in so much detail because I had to go to great lengths to find out how this works and I figured it might save someone else that time. I hope it was useful.

aryayush