Scrolling a UIView to keep the keyboard from obstructing the view of the current UITextField
Wow, that’s an unwieldy title!
Anyway, during some spare time today I’ve struggled with something in Objective C and Cocoa Touch that I’ve been struggling with before. When a UITextField in an iOS app becomes ”active”, allowing the user to enter text, almost half of the screen gets covered by the software keyboard. That’s all well and good, but that keyboard is likely to obstruct the view of something, maybe even of the UITextField in question and that’s not good.
To avoid this problem, I the developer am supposed to move or resize (or something) the view. There are multiple questions about this on StackOverflow and multiple answers. After some digging and a lot of trial and error I came up with a solution that differed at least somewhat from all other solutions that I could find. As far as I can tell my solution works and it’s pretty short in terms of code, which I like.
I don’t know, maybe it’s a bad solution. If so, please let me know.
The solution
First, embed all the views that need to move inside a UIScrollView.
In my case I have multiple UITextFields that needs to move so I placed them all inside a UIScrollView. I then added the following property to my ViewController:
1 2 |
@property (strong, nonatomic) UITextField *activeTextField; |
This property is updated on textFieldShouldBeginEditing
like so:
1 2 3 4 5 |
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { self.activeTextField = textField; return true; } |
Then , in my viewDidLoad
I added the following two observers:
1 2 3 |
[ [ NSNotificationCenter defaultCenter ] addObserver:self selector:@selector( keyboardDidShow: ) name:UIKeyboardDidShowNotification object:nil ]; [ [ NSNotificationCenter defaultCenter ] addObserver:self selector:@selector( keyboardDidHide ) name:UIKeyboardDidHideNotification object:nil ]; |
These will trigger the methods keyboardDidShow
and keyboardDidHide
when the keyboard appears and disappears respectively. It is in those methods that ”the magic” happens:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
- (void)keyboardDidShow:( NSNotification *)notification { // Find out the frame of the keyboard NSDictionary *userInfo = [notification userInfo]; CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; // Calculate how heigh of an available content area we have now by // subtracting the keyboards height from the height of the main view. NSInteger heightOfAvailableContentArea = self.view.frame.size.height - keyboardFrame.size.height; // Make a point with a y that's the y of the activeTextField minus half // the height of the available content area and then scroll the // UIScrollView to this position. CGPoint scrollPoint = CGPointMake( 0, self.activeTextField.frame.origin.y - heightOfAvailableContentArea / 2 ); [ self.scrollView setContentOffset:scrollPoint animated:YES ]; } - (void)keyboardDidHide { // Return the UIScrollView to 0 position. CGPoint scrollPoint = CGPointMake( 0, 0 ); [ self.scrollView setContentOffset:scrollPoint animated:YES ]; } |
Coda
As I said, this works but it’s very possible that it’s a bad solution. If you like the solution, feel free to use it. If you think it’s bad, please tell me so and why so that I can learn and become a better programmer.
Replies and comments
Henrik Carlsson's Blog
8 juli, 2011 00:32[…] week I wrote a blog post about my upcoming trip to Warsaw with the band Hedningarna and the fact that I would use my iPad as my main digital entertainment […]