问题
I'm writing an app targeting iOS 6.1. I'm trying to follow this Apple doc on how to scroll a UITextField into view if it is obscured by the keyboard. The problem is that Apple's documented algorithm for calculating the scroll point doesn't work so well. My algorithm for calculating the scroll point works only slightly better, but is off by 70 pixels. What is the correct way to calculate the scroll point?
Below you can see, from left to right, my view before the keyboard is shown, my view after scrolling using Apple's algorithm to calculate the scroll point, and my view after scrolling using my algorithm to calculate the scroll point. (Each square in that grid is 25 pixels by 25 pixels.)
And here is the code I am using. Note the #if APPLE_WAY
block.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
self.view.contentInset = contentInsets;
self.view.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.activeField.frame.origin) ) {
#if APPLE_WAY
CGPoint scrollPoint = CGPointMake(0.0, self.activeField.frame.origin.y-kbSize.height);
#else
CGFloat offset = self.activeField.frame.origin.y;
//TODO: Why is this off by 70?
offset = offset - 70;
CGPoint scrollPoint = CGPointMake(0.0, offset);
#endif
[self.view setContentOffset:scrollPoint animated:YES];
}
}
回答1:
You simply need to set the offset to the height of the keyboard:
CGFloat offset = kbSize.height;
CGPoint scrollPoint = CGPointMake(0.0, offset);
[self.view setContentOffset:scrollPoint animated:YES];
hope this helps
回答2:
There are a few ways to do this. Given your situation, I would do something like this:
- (void)keyboardWasShown:(NSNotification *)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.activeField.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, self.activeField.frame.origin.y-kbSize.height);
[self.scrollView setContentOffset:scrollPoint animated:YES];
}
}
- (void)keyboardWillBeHidden:(NSNotification *)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.activeField.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0, 0);
[self.scrollView setContentOffset:scrollPoint animated:YES];
}
}
Then, in your viewDidLoad method:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
回答3:
It's easy when what you've got is a scroll view, because you don't even have to scroll; all you have to do is adjust the contentInset and scrollIndicatorInsets to get out of the keyboard's way, and the rest happens automatically:
- (void) keyboardShow: (NSNotification*) n {
self->_oldContentInset = self.scrollView.contentInset;
self->_oldIndicatorInset = self.scrollView.scrollIndicatorInsets;
self->_oldOffset = self.scrollView.contentOffset;
NSDictionary* d = [n userInfo];
CGRect r = [[d objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
r = [self.scrollView convertRect:r fromView:nil];
CGRect f = self.fr.frame;
CGFloat y =
CGRectGetMaxY(f) + r.size.height -
self.scrollView.bounds.size.height + 5;
if (r.origin.y < CGRectGetMaxY(f))
[self.scrollView setContentOffset:CGPointMake(0, y) animated:YES];
UIEdgeInsets insets;
insets = self.scrollView.contentInset;
insets.bottom = r.size.height;
self.scrollView.contentInset = insets;
insets = self.scrollView.scrollIndicatorInsets;
insets.bottom = r.size.height;
self.scrollView.scrollIndicatorInsets = insets;
}
I give a bunch of different strategies, with code, in this section of my book:
http://www.apeth.com/iOSBook/ch23.html#_keyboard_covers_text_field
All of that is backed by downloadable projects that you can grab at my github site.
来源:https://stackoverflow.com/questions/15802015/scrolling-uitextfield-into-view-when-keyboard-is-shown