I'm loading a UIWebView in a modal. The web page has some inputs that work exactly as intended in iOS 5. However in iOS 6, anytime an input gets focus, the keyboard is doing it's automatic 'centering' of the form even though the inputs have plenty of room to be shown above the keyboard. Since some of the inputs are at the top of the page, this forces them out of view so the user cannot see what they are typing. Scrolling back up to see the inputs causes the keyboard to stop working until dismissed and refocusing the input (in turn scrolling it out of view again). Is this an expected behavior in iOS 6? Is there any way to keep the webview from scrolling when an input gains focus (like how iOS 5 works)?
问题:
回答1:
Without knowing the inner workings of your code, I'm going to try to help as much as I can. If nothing else, I hope to provide some food for thought. You asked two questions:
Is it expected behavior in iOS6?
What you're seeing is quite odd for sure. It's strange that the webView is centering the form rather than centering the input field. And it should definitely not cause the active input field to scroll out of view. Furthermore, the keyboard seems to stop working, which is quite odd. However, it is expected to see different behavior in iOS 5 and 6 with regards to the webView scrolling. As you said, iOS 5 scrolls the inputField into view while iOS6 puts it in center.
Is there any way to keep the webview from scrolling when an input gains focus (like how iOS 5 works)?
Yes. I provide code to do just this below -- namely to stop the webView from scrolling. If that is exactly what you want to do, then great. However, stopping the webView from scrolling is not the same as getting the same behavior as iOS5. Still, I wanted to give you this option as you requested it.
#import "ViewController.h"
@interface ViewController () <UIScrollViewDelegate> {
CGPoint origin;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.google.com"]];
[self.webView loadRequest:request];
self.webView.scrollView.delegate = self;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow)
name:UIKeyboardWillShowNotification
object:nil];
// NOTE THAT SIMPLY DISABLING THE SCROLL WILL NOT PREVENT KEYBOARD SCROLL
//[self.webView.scrollView setScrollEnabled:NO];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)keyboardWillShow {
NSLog(@"keyboard");
origin = self.webView.scrollView.contentOffset;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(@"scroll");
[self.webView.scrollView setContentOffset:origin];
}
@end
If you want consistent scroll behavior...
I took some time to code up this scroll modification. You can use it as a reference in making your own scroll behavior that is consistent across iOS 5&6. In this code: When the user clicks on a text input box on a webpage, the code will stop the default scrolling behavior by keeping the page scrolled to its current position. Unfortunately, there is no way to cancel all scrolling, but rather you have to override scrolls. Once the default scrolling has been "suppressed", it gets the position of the active input box and scrolls to that position. This will put the active input box in the top of the screen. You can modify this according to your preferences. For example, you can use [UIScrollView scrollRectToVisible] to make it more like iOS5.
#import "ViewController.h"
@interface ViewController () <UIScrollViewDelegate> {
CGPoint origin;
CGPoint activeElementOrigin;
BOOL pauseScroll;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.google.com"]];
[self.webView loadRequest:request];
self.webView.scrollView.delegate = self;
pauseScroll = NO;
origin = CGPointZero;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidShow)
name:UIKeyboardDidShowNotification
object:nil];
}
- (void)keyboardWillShow {
NSLog(@"keyboard");
pauseScroll = YES;
origin = self.webView.scrollView.contentOffset;
}
- (void)keyboardDidShow {
NSLog(@"keyboard DID SHOW");
pauseScroll = NO;
[self.webView.scrollView setContentOffset:activeElementOrigin animated:YES];
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(@"scroll");
if (pauseScroll) {
[self.webView.scrollView setContentOffset:origin animated:NO];
NSString *javaScript = [NSString stringWithFormat:@"function f(){ var textField = document.activeElement; return textField.getBoundingClientRect().top; } f();"];
NSString *textFieldRectTop = [self.webView stringByEvaluatingJavaScriptFromString:javaScript];
activeElementOrigin = origin;
activeElementOrigin.y = [textFieldRectTop floatValue]-10;
}
}
@end
If this code helped you, it would be very nice of you to reward the bounty to me. I would be humbly appreciative.
回答2:
A workaround could be disabling the scroll in this UIWebView :
UIScrollView *scrollView = webView.scrollView;
[scrollview setScrollEnabled:NO];
[scrollView bounces:NO];
Another could be setting the UIEdgeInsets of this scrollView but I don't know much about this.
I think this is a standard behaviour in both iOS 5 and 6 to scroll to make the input field just on top of te keyboard (just like Safari does).
回答3:
The checked answer on this post has your answer: How to make a UITextField move up when keyboard is present?
In short, you need to move up the view containing the inputs which are being pushed out of view. The post also contains sample code on how to do it.
Hope this helps.