[ios] Stop UIWebView from "bouncing" vertically?

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

How do I stop a UIScrollView from bouncing horizontally?

This question is related to ios objective-c iphone uiscrollview uiwebview

The answer is


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.

turning off vertical scrolling

digging into pastrykit


In Swift to disable bounces

webViewObj.scrollView.bounces = false

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.


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.


Well all I did to accomplish this is :

UIView *firstView = [webView.subviews firstObject];

if ([firstView isKindOfClass:[UIScrollView class]]) {

    UIScrollView *scroll = (UIScrollView*)firstView;
   [scroll setScrollEnabled:NO];  //to stop scrolling completely
   [scroll 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.


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.


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


Came across this searching for an answer and I eventually just lucked on an answer of my own by messing about. I did

[[webview scrollView] setBounces:NO];

and it worked.


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.

(Xcode 5 iOS 7 SDK example) Here is a Universal App example using the scrollview setBounces function. It is an open source project / example located here: Link to SimpleWebView (Project Zip and Source Code Example)


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


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.

turning off vertical scrolling

digging into pastrykit


I tried a slightly different approach to prevent UIWebView objects from scrolling and bouncing: adding a gesture recognizer to override other gestures.

It seems, UIWebView or its scroller subview uses its own pan gesture recognizer to detect user scrolling. But according to Apple's documentation there is a legitimate way of overriding one gesture recognizer with another. UIGestureRecognizerDelegate protocol has a method gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: - which allows to control the behavior of any colliding gesture recognizers.

So, what I did was

in the view controller's viewDidLoad method:

// Install a pan gesture recognizer                                                                                        // We ignore all the touches except the first and try to prevent other pan gestures                                                     
// by registering this object as the recognizer's delegate                                                                                        
UIPanGestureRecognizer *recognizer;                                                                                                               
recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)];                                                   
recognizer.delegate = self;                                                                                                                       
recognizer.maximumNumberOfTouches = 1;                                                                                                            
[self.view addGestureRecognizer:recognizer];                                                                                                          
self.panGestureFixer = recognizer;                                                                                                                  
[recognizer release]; 

then, the gesture override method:

// Control gestures precedence                                                                                                                            
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer                                                                                        
        shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer                                                  
{                                                                                                                                                         
        // Prevent all panning gestures (which do nothing but scroll webViews, something we want to disable in                                          
        // the most painless way)                                                                                                                         
        if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])                                                                        
        {
            // Just disable every other pan gesture recognizer right away                                                                             
            otherGestureRecognizer.enabled = FALSE;
        }                                                                                                                                                  
        return NO;                                                                                                                                        
}              

Of course, this delegate method can me more complex in a real application - we may disable other recognizers selectively, analyzing otherGestureRecognizer.view and making decision based on what view it is.

And, finally, for the sake of completeness, the method we registered as a pan handler:

- (void)handlePanFrom:(UIPanGestureRecognizer *)recognizer 
{ 
    // do nothing as of yet
}

it can be empty if all we want is to cancel web views' scrolling and bouncing, or it can contain our own code to implement the kind of pan motions and animations we really want...

So far I'm just experimenting with all this stuff, and it seems to be working more or less as I want it. I haven't tried to submit any apps to iStore yet, though. But I believe I haven't used anything undocumented so far... If anyone finds it otherwise, please inform me.


On iOS5 only if you plan to let the users zoom the webview contents (e.i.: double tap) the bounce setting isn't enough. You need to set also alwaysBounceHorizontal and alwaysBounceVertical properties to NO, else when they zoom-out (another double tap...) to default it will bounce again.


Well all I did to accomplish this is :

UIView *firstView = [webView.subviews firstObject];

if ([firstView isKindOfClass:[UIScrollView class]]) {

    UIScrollView *scroll = (UIScrollView*)firstView;
   [scroll setScrollEnabled:NO];  //to stop scrolling completely
   [scroll 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.


To disable UIWebView scrolling you could use the following line of code:

[ObjWebview setUserInteractionEnabled:FALSE];

In this example, ObjWebview is of type UIWebView.


In Swift to disable bounces

webViewObj.scrollView.bounces = false

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.

This worked for me, and beautifully too (I am using phonegap with webView)

[[webView.webView scrollView] setScrollEnabled:NO];

or

[[webView scrollView] setScrollEnabled:NO];

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.


fixed positioning on mobile safari

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


To disable UIWebView scrolling you could use the following line of code:

[ObjWebview setUserInteractionEnabled:FALSE];

In this example, ObjWebview is of type UIWebView.


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.


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


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


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.


In the iOS 5 SDK you can access the scroll view associated with a web view directly rather than iterating through its subviews.

So to disable 'bouncing' in the scroll view you can use:

myWebView.scrollView.bounces = NO;

See the UIWebView Class Reference.

(However if you need to support versions of the SDK before 5.0, you should follow Mirek Rusin's advice.)


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


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


On iOS5 only if you plan to let the users zoom the webview contents (e.i.: double tap) the bounce setting isn't enough. You need to set also alwaysBounceHorizontal and alwaysBounceVertical properties to NO, else when they zoom-out (another double tap...) to default it will bounce again.


Came across this searching for an answer and I eventually just lucked on an answer of my own by messing about. I did

[[webview scrollView] setBounces:NO];

and it worked.


I tried a slightly different approach to prevent UIWebView objects from scrolling and bouncing: adding a gesture recognizer to override other gestures.

It seems, UIWebView or its scroller subview uses its own pan gesture recognizer to detect user scrolling. But according to Apple's documentation there is a legitimate way of overriding one gesture recognizer with another. UIGestureRecognizerDelegate protocol has a method gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: - which allows to control the behavior of any colliding gesture recognizers.

So, what I did was

in the view controller's viewDidLoad method:

// Install a pan gesture recognizer                                                                                        // We ignore all the touches except the first and try to prevent other pan gestures                                                     
// by registering this object as the recognizer's delegate                                                                                        
UIPanGestureRecognizer *recognizer;                                                                                                               
recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)];                                                   
recognizer.delegate = self;                                                                                                                       
recognizer.maximumNumberOfTouches = 1;                                                                                                            
[self.view addGestureRecognizer:recognizer];                                                                                                          
self.panGestureFixer = recognizer;                                                                                                                  
[recognizer release]; 

then, the gesture override method:

// Control gestures precedence                                                                                                                            
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer                                                                                        
        shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer                                                  
{                                                                                                                                                         
        // Prevent all panning gestures (which do nothing but scroll webViews, something we want to disable in                                          
        // the most painless way)                                                                                                                         
        if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])                                                                        
        {
            // Just disable every other pan gesture recognizer right away                                                                             
            otherGestureRecognizer.enabled = FALSE;
        }                                                                                                                                                  
        return NO;                                                                                                                                        
}              

Of course, this delegate method can me more complex in a real application - we may disable other recognizers selectively, analyzing otherGestureRecognizer.view and making decision based on what view it is.

And, finally, for the sake of completeness, the method we registered as a pan handler:

- (void)handlePanFrom:(UIPanGestureRecognizer *)recognizer 
{ 
    // do nothing as of yet
}

it can be empty if all we want is to cancel web views' scrolling and bouncing, or it can contain our own code to implement the kind of pan motions and animations we really want...

So far I'm just experimenting with all this stuff, and it seems to be working more or less as I want it. I haven't tried to submit any apps to iStore yet, though. But I believe I haven't used anything undocumented so far... If anyone finds it otherwise, please inform me.


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;
    }
}

webView.scrollView.scrollEnabled=NO; webView.scrollView.bounces=NO;


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.


In the iOS 5 SDK you can access the scroll view associated with a web view directly rather than iterating through its subviews.

So to disable 'bouncing' in the scroll view you can use:

myWebView.scrollView.bounces = NO;

See the UIWebView Class Reference.

(However if you need to support versions of the SDK before 5.0, you should follow Mirek Rusin's advice.)


This worked for me, and beautifully too (I am using phonegap with webView)

[[webView.webView scrollView] setScrollEnabled:NO];

or

[[webView scrollView] setScrollEnabled:NO];

Swift 3

webView.scrollView.bounces = false

fixed positioning on mobile safari

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


Swift 3

webView.scrollView.bounces = false

(Xcode 5 iOS 7 SDK example) Here is a Universal App example using the scrollview setBounces function. It is an open source project / example located here: Link to SimpleWebView (Project Zip and Source Code Example)


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;
    }
}

webView.scrollView.scrollEnabled=NO; webView.scrollView.bounces=NO;


Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to objective-c

Adding a UISegmentedControl to UITableView Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Warp \ bend effect on a UIView? Use NSInteger as array index Detect if the device is iPhone X Linker Command failed with exit code 1 (use -v to see invocation), Xcode 8, Swift 3 ITSAppUsesNonExemptEncryption export compliance while internal testing? How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem? Change status bar text color to light in iOS 9 with Objective-C

Examples related to iphone

Detect if the device is iPhone X Xcode 8 shows error that provisioning profile doesn't include signing certificate Access files in /var/mobile/Containers/Data/Application without jailbreaking iPhone Certificate has either expired or has been revoked Missing Compliance in Status when I add built for internal testing in Test Flight.How to solve? cordova run with ios error .. Error code 65 for command: xcodebuild with args: "Could not find Developer Disk Image" Reason: no suitable image found iPad Multitasking support requires these orientations How to insert new cell into UITableView in Swift

Examples related to uiscrollview

How can I mimic the bottom sheet from the Maps app? Is it possible for UIStackView to scroll? Set UITableView content inset permanently UIScrollView Scrollable Content Size Ambiguity How to use UIScrollView in Storyboard Get UIScrollView to scroll to the top How to scroll UITableView to specific position Disabling vertical scrolling in UIScrollView How do I auto size a UIScrollView to fit its content UIScrollView not scrolling

Examples related to uiwebview

How to display .svg image using swift Can I set the cookies to be used by a WKWebView? How to Migrate to WKWebView? iOS JavaScript bridge How to load local html file into UIWebView Load resources from relative path using local html in uiwebview Clearing UIWebview cache How to determine the content size of a UIWebView? UIWebView open links in Safari Can we open pdf file using UIWebView on iOS?