Set UIWebView Content not to Scroll When Keyboard is Shown

On February 18, 2016, in iPhone iPad Object-C, by James Liu

This week, I have met a problem when I am developing a hybrid app with Cordova (Phonegap). The Cordova app is basing on UIWebView. So the whole app is build by HTML5, Javascript and CSS. Usually, UIWebView will scroll up when keyboard is shown if we click an input field or textfield focus. Therefore, all content in the UIWebView is pushing up. In most of the case, this behavior is correct. However, in my case, it becomes to be a problem. And I have to prevent UIWebView to scroll when keyboard appears.

Let me describe my problem first. I am using Cordova (Phonegap) to build an iOS app. The whole app is basing on UIWebView. In my app, I have a fixed div header at UIWebView top and a fixed div footer at UIWebView bottom. In the middle of the content, there is an input text field. When I click on the input text field and get the input text field focused, all content in UIWebView will scroll up, including the fixed header and fixed footer, which I really don’t want. I have to find a way to set UIWebView content not move when soft keyboard is shown in iOS app.

Javascript Solution

At the beginning, I search on Google and find lots of solutions. One solution is using Javascript to scroll the html content down when the soft keyboard popups. Here is the basic idea:

$('input').on('focus', function(e) {

However, it doesn’t work on new iOS version. Therefore, there is an improved Javascript solution:

$('input').on('focus', function(e) {
			windows.scrollTo(0, 0);
		}, 100);

But the improved Javascript is not ideal, sometimes you can still see a little jitter animation. To solve the problem perfectly, I have to go deep and try to solve the problem with native objective-c code.

Native Solution

When we click the input field in UIWebView, the soft keyboard will appear and push all content up. It is a built-in feature in iOS. The UIWebView has a UIScrollView inside, which will move the content up and down. Now the solution is disabling the UIScrollView scrolling content up in the UIWebView.

Some people says we can using following code to disable scroll view scrolling:

myWebView.scrollView.scrollEnabled = NO;

Unfortunately, the above code will not prevent keyboard pushing up webview at iOS using PhoneGap (Cordova). It only disable user interaction. User will not be able to scroll the webview any more. It is definitely not what we want.

The Working Solution in Native Code

Another way to stop scroll view scrolling is seting the UIScrollViewDelegate of UIScrollView, then over write the scrollViewDidScroll delegate function. Now the problem is how we can set the delegate and it will not affect the original UIWebView function.

Actually, we can observer the notification when the soft keyboard gets ready to appear and after appearing. In iOS, there will be two local notifications sent out when the soft keyboard is showing up.

  • UIKeyboardWillShowNotification: this notification will be sent out when the soft keyboard is going to show up.
  • UIKeyboardDidShowNotification: this notification will be sent out after the soft keyboard appears.

So we can first set UIScrollView delegate to our customized UIScrollViewDelegate before keyboard appears and set UIScrollView delegate back once keyboard appears. Now, let’s see how I implement this solution in Objective-C. Please check these example source code.

First, set the observer of above local notifications:

    [[NSNotificationCenter defaultCenter] addObserver:self
                                                 name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                                 name:UIKeyboardWillShowNotification object:nil];

Second, implement the observer functions:

- (void)keyboardWillShown:(NSNotification*)aNotification
    oldScrollDelegate = viewController.webView.scrollView.delegate;
    oldOffset = viewController.webView.scrollView.contentOffset;
    viewController.webView.scrollView.delegate = self;

- (void)keyboardWasShown:(NSNotification*)aNotification
    viewController.webView.scrollView.delegate = oldScrollDelegate;

Third, implement the UIScrollViewDelegate function to disable the scrolling feature of the UIScrollView.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    scrollView.contentOffset = oldOffset;

In this way, when the keyboard is going to show up, I set the UIScrollView’s delegate to self, and UIScrollView will always scroll to point (0, 0). After the keyboard appears, I set the UIScrollView’s delegate back to its old delegate, which will make UIScrollView working as what it should be.

Fixed Header Push Up When Scrolling

This is another problem when I use fixed div in iOS UIWebView. When I scroll my page in UIWebView, the fixed div is pushed up, just like a normal div. Actually, it could be solved by adding following meta data in html header:

<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
Tagged with:  

Leave a Reply

Free WordPress Theme

Free WordPress Theme