views:

11127

answers:

22

Hi there;

Does anyone know how to stop a UIWebView from bouncing vertically? I mean when a user touches their iphone screen, drags their finger downwards, and the webview shows a blank spot above the web page I had loaded?

I've looked at the following possible solutions, but none of them worked for me:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/996-turn-off-scrolling-bounces-uiwebview.html

http://forums.macrumors.com/showthread.php?t=619534

http://stackoverflow.com/questions/173786/how-do-i-stop-a-uiscrollview-from-bouncing-horizontally

Thanks!

Brad

A: 

One of the subviews of UIWebView should be a UIScrollView. Set its scrollEnabled property to NO and the web view will have scrolling disabled entirely.

Note: this is technically using a private API and thus your app could be rejected or crash in future OS releases. Use @try and respondsToSelector

rpetrich
I tried this out, and it faults when I try it... Strangely, i can access and set scrollView.bounces (with no effect), but when I try and set scrollEnabled, it faults...
Brad Parks
I believe the subview is called UIScroller, not UIScrollView.UIScroller is an undocumented and unsupported class that shares a lot in common with UIScrollView, but you can't depend on everything working the same way and not changing in future OS versions.
Marco
I did this on an iPad (not iPhone) app running iOS 3.2, and was able to get a UIScrollView out of my UIWebView. I successfully customized this view to change more than just its bouncing behavior so I can testify to this working on iPad.My app did not go through the app store, but I don't think there will be a problem with undocumented API's here. The clever part for this solution is that you're just traversing a UIView hierarchy and using a UIScrollView - both of which are perfectly kosher.
Rolf Hendriks
+6  A: 

If your webview doesnt need scrolling and doesnt need to handle links, you can set

mywebview.userInteractionEnabled = FALSE

so your webview will not respond to touches.

Stephan Burlot
A: 

Look into the bounces property of UIScrollView. Quoth the Apple docs:

If the value of the property is YES (the default), the scroll view bounces when it encounters a boundary of the content. Bouncing visually indicates that scrolling has reached an edge of the content. If the value is NO, scrolling stops immediately at the content boundary without bouncing.

Make sure you're using the right UIScrollView. I'm not sure what the hierarchy looks like for a UIWebView, but the scroll view could be a parent, not a child, of the UIWebView.

Alex
+14  A: 

I tried all of the above approaches, with no success... but I was looking at a project that makes it easy to create web apps as full fledged installable applications on the iPhone called QuickConnect, and found a solution that works, if you don't want your screen to be scrollable at all, which in my case I didn't.

In the above mentioned project/blog post, they mention a javascript function you can add to turn off the bouncing, which essentially boils down to this:

    document.ontouchmove = function(event){
        event.preventDefault();
    }

If you want to see more about how they implement it, simply download QuickConnect and check it out.... But basically all it does is call that javascript on page load... I tried just putting it in the head of my document, and it seems to work fine.

Brad Parks
I found an objective c solution on the following blog post:http://kwigbo.com/wp/2009/06/16/iphone-sdk-uiwebview-stop-bounce/It's basically this: [(UIScrollView*)yourWebView.subviews objectAtIndex:0] setAllowsRubberBanding:NO];Look lower on this page for a little more info!
Brad Parks
As @Raf mentioned below, the "setAllowsRubberBanding" method is private, and if used in an app, it stands a large chance of being rejected:http://stackoverflow.com/questions/500761/stop-uiwebview-from-bouncing-vertically/1743647#1743647
Brad Parks
This answer is the correct way to stop the vertical scrolling of the content within a UIWebView.
Jessedc
You could have given the whole answer, firstly I don't want to download a whole scource code of another app, and I can't even find it. Your answer relies on another website being the same as when you answered.
Jonathan
Kalle
+6  A: 

Also please note, contrary to popular belief, UIWebView is NOT a UIScrollView

nduplessis
A: 

Did you ever get this working...? I have a UIWebView that I just want to show a webpage... The entire view is bouncing - ie you see the gray behind the view when you try to scroll the contents of the UIWebView...

Jay Van Vark
just add what is says in my answer above.... add the document.ontouchmove javascript code.... and it works..... the page doesn't scroll...
Brad Parks
A: 

NOTE: It seems Apple is now using a static analyzer to process all appstore submissions and check for use of private APIs, so as @Meroon and @Raf have pointed out, use this and your app WILL be rejected by Apple

Hey there.. I found an objective c solution on the following blog post:

http://kwigbo.com/wp/2009/06/16/iphone-sdk-uiwebview-stop-bounce/

It's basically this:

[(UIScrollView*)yourWebView.subviews objectAtIndex:0] setAllowsRubberBanding:NO];

When you go to compile, it'll warn you that the method doesn't exist, but when you run your app, the rubber banding is completely turned off, and the page is still scrollable too, so it definitely works. I compiled with SDK 2.0, for what it's worth.

Also, since this method doesn't appear official (ie warning of unknown method) it may not be ok to use in an app submitted to the appstore, but who knows, maybe it is ;-)

Brad

Brad Parks
I can say for certain this will get your app rejected. My app just did because of this.
Meroon
Agreed, this comment should be taken out.
tomdemuyt
Under *NO CIRCUMSTANCES* should you ever do this. Brad, even with the disclaimer, you should delete this code since the person asking this question marked your answer as accepted. It is very very wrong.
thefaj
Thanks for your suggestion, @thefaj... while I'm not going to delete it, I am changing the accepted answer to another solution, as I was also the person that asked this question. Others may research the problem, and find this solution elswhere on the web, and wonder why it wasn't used. This way, they can see why!
Brad Parks
+3  A: 

Brad's method worked for me. If you use it you might want to make it a little safer.

id scrollView = [yourWebView.subviews objectAtIndex:0];
if( [scrollView respondsToSelector:@selector(setAllowsRubberBanding:)] )
{
    [scrollView performSelector:@selector(setAllowsRubberBanding:) withObject:NO];
}

If apple changes something then the bounce will come back - but at least your app won't crash.

Gavin Maclean
+5  A: 

Warning. I used setAllowsRubberBanding: in my app, and Apple rejected it, stating that non-public API functions are not allowed (cite: 3.3.1)

Raf
A: 

I just got an email from Apple stating that my app was rejected for "setAllowsRubberBanding:NO" as being a private API.

Then 4 minutes later I got another email saying that it was approved. I checked iTunes and my new version is available.

Another case of Apple's inconsistent approval process?

Anyway, I think it's safe to say that I need to find another method to disable bouncing in my webviews if I'm to put out another update.

RyeMAC3
A: 

As Brad Parks says, my app just got rejected for using that code.

Micah
A: 

I'm running into a case where the ontouchmove doesn't completely stop the bounce. It works OK as long as the touch stays within the UIWebView frame but as soon as you move out of the frame it starts scrolling. Anyone else encounter this problem?

Richard Burgess
I'm seeing the same thing. I would REALLY like to stop this.Any ideas?
Axeva
+1  A: 

Here's two newer potential solutions. Apparently, you can use jqtouch or pastrykit to disable scrolling. However, I haven't got these to work. You might be more competent.

http://blog.jqtouch.com/post/285889760/turning-off-vertical-scrolling

http://waynepan.com/2009/12/16/digging-into-pastrykit

cannyboy
+1  A: 

http://doctyper.com/archives/200808/fixed-positioning-on-mobile-safari/

This link helped me lot.....Its easy.. There is a demo..

Sijo
+1  A: 

I traversed the collection of UIWebView's subviews and set their backgrounds to [UIColor blackColor], the same color as the webpage background. The view will still bounce but it will not show that ugly dark grey background.

pedro
This is the best suggestion on here!
Frank Krueger
Actually it's a pretty bad one, because if Apple ever changes the internals of UIWebView, this hack could break.
bpapa
A: 

It looks to me like the UIWebView has a UIScrollView. You can use documented APIs for this, but bouncing is set for both directions, not individually. This is in the API docs. UIScrollView has a bounce property, so something like this works (don't know if there's more than one scrollview):

NSArray *subviews = myWebView.subviews;
NSObject *obj = nil;
int i = 0;
for (; i < subviews.count ; i++)
{
    obj = [subviews objectAtIndex:i];

    if([[obj class] isSubclassOfClass:[UIScrollView class]] == YES)
    {
        ((UIScrollView*)obj).bounces = NO;
    }
}
spymaster
+1  A: 

I was annoyed to find out that UIWebView is not a scroll view, so I made a custom subclass to get at the web view's scroll view. This suclass contains a scroll view so you can customize the behavior of your web view. The punchlines of this class are:

@class CustomWebView : UIWebview
...

- (id) initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
// WebViews are subclass of NSObject and not UIScrollView and therefore don't allow customization.
// However, a UIWebView is a UIScrollViewDelegate, so it must CONTAIN a ScrollView somewhere.
// To use a web view like a scroll view, let's traverse the view hierarchy to find the scroll view inside the web view.
for (UIView* v in self.subviews){
    if ([v isKindOfClass:[UIScrollView class]]){
        _scrollView = (UIScrollView*)v; 
        break;
    }
}
return self;

}

Then, when you create a custom web view, you can disable bouncing with:

customWebView.scrollView.bounces = NO; //(or customWebView.scrollView.alwaysBounceVertically = NO)

This is a great general purpose way to make a web view with customizable scrolling behavior. There are just a few things to watch out for:

  • as with any view, you'll also need to override -(id)initWithCoder: if you use it in Interface Builder
  • when you initially create a web view, its content size is always the same as the size of the view's frame. After you scroll the web, the content size represents the size of the actual web contents inside the view. To get around this, I did something hacky - calling -setContentOffset:CGPointMake(0,1)animated:YES to force an unnoticeable change that will set the proper content size of the web view.
Rolf Hendriks
A: 

Is any one find the solution and also apple approve that? I posted the message on devforum but no one replay back. Is it safe now to use this code?

[(UIScrollView*)yourWebView.subviews objectAtIndex:0] setAllowsRubberBanding:NO]

Adeem Maqsood Basraa
+19  A: 
for (id subview in webView.subviews)
  if ([[subview class] isSubclassOfClass: [UIScrollView class]])
    ((UIScrollView *)subview).bounces = NO;

...seems to work fine.

It'll be accepted to App Store as well.

Mirek Rusin
Can someone verify this quickly ?
tomdemuyt
It works. No subclassing required and if Apple ever change the UIWebView hierarchy, it shouldn't crash.
leolobato
works smoothly.
Tudorizer
This fix seems to only work in my OS 4.1 Simulator, not on my OS 3.1.3 iPhone. Does anybody know if this fix only works on particular OS versions?
Dan J
A: 

I have been trying to solve this for a few hours now. The Javascript method above works if you want no scrolling at all, however if you want scrolling with no bounce it doesn't do the trick.

I tried using the document.ontouchmove event to dectect and stop the bounce but after some testing I noticed this stops firing when the bounce starts so it was no good for fixing this problem.

I have however found a fix, mostly by mining other stack overflow answers so a big thanks to the community. Please note I'm very new to Objective-C so please test this properly if you use it.

You can stop the bouncing but keep the scrolling by placing your UIWebView inside a UIScrollView and disabling the scrollviews bounces property.

Create the UIWebView like the following:

NSString *html = @"<html><head></head><body><div id=\"details\">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In non turpis tellus, ac tempus urna. Nunc fermentum nunc in felis cursus vel aliquam mi scelerisque. Nullam sollicitudin varius porta. Integer vel neque sapien. Vivamus ut sodales ligula. Nunc non sodales nibh. Integer vitae est diam. Nullam vehicula imperdiet congue. Aliquam interdum, urna tempus faucibus rutrum, tortor ante rutrum felis, id laoreet dolor velit vel lorem. Donec varius quam id turpis vulputate lobortis. Pellentesque vestibulum sodales pretium. Vivamus laoreet imperdiet condimentum. Donec ut felis non sem euismod commodo. Pellentesque id ante ac justo blandit luctus.\n\nMaecenas euismod tristique faucibus. Proin et tortor vulputate nibh congue pellentesque. Curabitur elit nulla, accumsan congue mollis non, tincidunt eget augue. Vivamus a dolor metus, eu ornare ligula. Quisque libero augue, iaculis quis imperdiet non, facilisis interdum nisi. Aliquam massa risus, varius euismod rutrum et, imperdiet vel ante. Vestibulum eu sapien aliquam purus rutrum ultrices porttitor non massa. Nam vestibulum est et sapien consectetur non consectetur nibh convallis. Mauris vulputate diam id leo eleifend fringilla. Integer et dui diam, sed ultricies leo. Nam massa lacus, auctor eget gravida nec, sollicitudin id augue. Quisque pellentesque elementum lectus, a placerat ipsum ultrices ac. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris id lectus turpis, nec aliquet felis. Nam aliquam ullamcorper dolor, sed euismod lacus feugiat eget. Curabitur commodo nulla augue, et dapibus neque.</div></body></html>";

UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 290, 3000)];
webView.delegate = self;
[webView loadHTMLString:html baseURL:nil];

// Keep as an IVar as we need to set the content size later
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(5, 5, 290, 328)];
scrollView.bounces = NO;
[scrollView addSubview:webView];

Then add the following method to set the scrollview content size.

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *output = [webView stringByEvaluatingJavaScriptFromString:@"document.getElementById('details').offsetHeight;"];
    scrollView.contentSize = CGSizeMake(290, [output intValue] + 10);
}

I hope that helps.

Dominic Godin
A: 

Well all I did to accomplish this is :

[[webView.subviews objectAtIndex:0] setScrollEnabled:NO];  //to stop scrolling completely
[[webView.subviews objectAtIndex:0] setBounces:NO]; //to stop bouncing

Works fine for me... Also, the ticked answer for this question is one that Apple will reject if you use it in your iphone app.

A: 

Does anyone tried to submit an app that uses setScrollEnabled in UIWebView? Is it accepted?

techadorer