In the context of the iPhone:
I have a UIScrollView
containing a UIImage
. When the user taps the screen inside the UIImage
, a
Instead of changing the content offset, change the scroll view's display frame.
- (void)keyboardWill:(NSNotification*)notification
{
CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
// Update the scroll view's frame to the region not covered by the keyboard.
self.frame = CGRectMake(self.fullSizedFrame.origin.x,
self.fullSizedFrame.origin.y,
self.fullSizedFrame.size.width,
self.fullSizedFrame.size.height - keyboardSize.height);
}
- (void)keyboardWillHide:(NSNotification*)notification
{
// Set the frame back to the original frame before the keyboard was shown.
self.frame = self.fullSizedFrame;
}
If you don't allow the user to change screen orientation, then fullSizedFrame could be set to the original frame of the view when it is first displayed. If changes in orientation are allowed, you'll need to calculate the appropriate value for fullSizedFrame based on the orientation.
One possible workaround could be to respond to the scrollViewDidScroll
delegate method check to see if the UITextField
is hidden again, then re-scroll if necessary. Seems like a bit of a hack, but it sounds like the UIScrollView
auto scrolling behavior is what's getting in your way, and if there's no way to directly affect it, the only option is to work around it. There is also the disadvantage, however, that if you do this then it appears to scroll twice.
If the auto-scrolling behavior happens only when the UITextField
expands beyond the edge of the screen, you could also move the field to stay completely visible if it looks like it's going to expand beyond the edge of the screen.
Basically setFrame
of UIScrollView
will readjust the scrollview offset
, done by _adjustContentOffsetIfNecessary
. As that method is private and not documented, there is very little we can guess on how the adjustment will happen.
There are two ways to stop the unnecessary scrolling or wrong offset
being set:
1) reset the UIScrollView
offset
after applying setFrame
. This you can do, if you are modifying the frame of UIScrollView
intentionally based on some calculations.
CGPoint oldOffset = [scrollView contentOffset];
scrollView.frame = CGRectMake(newFrame);
[scrollView setContentOffset:oldOffset];
2) apply offset
changes without animation. In your keyboardWasShown
, change
[self setContentOffset:scrollPoint animated:YES]; to
[self setContentOffset:scrollPoint animated:NO];
Reason: when more than one offset
is applied with animation on, the result offset
is ambiguous. Here the internal method(_adjustContentOffsetIfNecessary
) applies an offset change and the other one is done by your code. You can notice this if you try to log all the offsets being applied in the UIScrollView
delegate method:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(@" offset: %@", NSStringFromCGPoint(scrollView.conentOffset))
}
Let me know if this helps.