8

I'm working on a browser app, and I have an address bar on top the UIWebView. On MobileSafari if you scroll down, the address bar starts to move to the top, out of the screen, and the UIWebView doesn't scroll. Only when the address bar disappears completely, it starts to scroll. I would like to have this effect in my app as well.

What's the best way to implement this?

Thanks

Alex1987
  • 9,397
  • 14
  • 70
  • 92

4 Answers4

15

The only way to implement this requires iOS 5. In iOS 5, UIWebView has an UIScrollView subview.

And use the following code:

Set a area for the address bar:

[[myWebView scrollView] setContentInset:UIEdgeInsetsMake(64, 0, 0, 0)];

Move the address bar using the scrollview delegate:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{

        if(scrollView.contentOffset.y>=-64&&scrollView.contentOffset.y<30)
        {
            topBar.frame=CGRectMake(0,-44-scrollView.contentOffset.y, 320, 44);

        }
        else if(scrollView.contentOffset.y<-64)
            topBar.frame=CGRectMake(0,20, 320, 44);//Lock the position
}
PeakJi
  • 1,547
  • 14
  • 23
  • Thanks man this really solved my problem. You can get the scrollView also by for (UIView *view in [webView subviews]){ if ([view isKindOfClass:[UIScrollView class]]){ UIScrollView *theScrollView = (UIScrollView *)view; return theScrollView; } } You also need to add the top Bar to the UIWebView as a subview – Alex1987 Oct 02 '11 at 08:43
  • @PeakJi Finally an answer that works for this! took me forever to find it. Thanks! – Crystal Aug 15 '12 at 18:12
  • I did this in iOS 6, but one issue i see is that when a web page loads or something, the top of the webview is automatically under the status bar or top of the phone, is there any way to fix so that its the navigation bar instead? – Maximilian Litteral Dec 30 '12 at 06:38
  • @MaxHasADHD sorry for my super late reply... Yes, UIWebview resets its content offset on 'didFinishLoading'. Maybe we could try some 'jerky' ways to do that(I don't know if these work): a. Use a timer to 'lock' the offset; b. Reset the offset after 'didFinishLoading' with delay; c.Remove the Content Inset temporarily. Have a try;-P – PeakJi Mar 06 '13 at 14:06
  • i had a problem where after adding a subview to the webview's scrollview half the webpage would be unclickable, i fixed it by inserting the subview at position 0 (so its at the back in the view hierarchy), not sure why it works but it did. – Fonix Jul 30 '13 at 09:23
4

There is a way, but I am not sure if it is a bit too hacky. First search for the scrollview within the webview, then alter the contentInset and finally add the searchbar(for example) to the scrollview. The following code is just an example, I did not set any frames correctly and 40 is just a made up height for the searchbar. I am not sure if this will work in every iOS Version.

UIWebView * myWebView = [[UIWebView alloc] init]
UISearchBar * mySearchBar = [[UISearchBar alloc] init];
for (NSObject * aSubView in [myWebView subviews]) {
   if ([aSubView isKindOfClass:[UIScrollView class]]) {
      UIScrollView * theScrollView = (UIScrollView *)aSubView;
      theScrollView.contentInset = UIEdgeInsetsMake(40, 0, 0, 0);
      [theScrollView addSubview:mySearchBar];
   }
}
Nick Weaver
  • 47,228
  • 12
  • 98
  • 108
  • I tried this on 4.2 and it works. Does the webview contain a "Scroller" class? – Nick Weaver Feb 27 '11 at 10:07
  • 4.3 still has a UIScrollView subview. Unless Apple deliberately makes a similarly functioning class with a different name, I doubt that they will change that. – Moshe Apr 07 '11 at 16:05
0

Come to think of it, it is simply a scrolling view with an address bar stuck on the top, and both the web view and the bar always move together. Now, lets say you create a scroll view and add two subviews, the address bar and the web view (one below the other). It is to be noted that the height of the web view is determined and fixed after the page has been loaded (in webViewDidFinishLoad:).

Hence, it is simply a scrolling view whose contentSize is equal to the height of the bar + the height of the web view. Now, by default the web view allows scrolling, as it has a scroll view as a subview. As only the outer scroll view should be scrolling, it is required that the web view's scrolling be turned off. For that, fetch the first subview (that's the scroll view) and disable its scrolling using:

(UIScrollView*)[myWebView.subviews objectAtIndex:0].scrollEnabled = NO;
Akshay
  • 5,747
  • 3
  • 23
  • 35
  • Have you actually implemented this effect? BTW how can the address bar be contained in the UIScrollView when the scrolling bars appear only in the UIWebView, when scrolling? – Alex1987 Sep 29 '11 at 07:41
  • No, I haven't implemented this myself. Also, is it important for you to exactly emulate the Safari UI? What I mentioned is functionally the same. The important thing is that the address bar should scroll off from the screen and not take up permanent space, so that more real estate is available for the web page. – Akshay Sep 29 '11 at 07:50
  • Well this issue has been on my mind for some time now. There are other apps on the appstore (like downloads lite) that emulate this behavior exactly... So I just wonder how can it be achieved. – Alex1987 Sep 29 '11 at 10:24
0

PeakJi's solution works but is a bit laggy. A better solution would be adding an observer to the UIScrollView's content offset, something like

[scrollview addObserver:self forKeyPath:@"contentOffset" 
                                    options:NSKeyValueObservingOptionNew context:nil];

You can find more document on NSKeyValueObserving protocol at

https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html

Mars Lan
  • 86
  • 3