Stop scrolling to top in UIWebView - iPhone - iphone

I have placed following javascript in my html file.
<script TYPE="text/javascript">
function srk(){
document.ontouchmove = function(e){
e.preventDefault();
}
}
</script>
I am scrolling my webview by following code with some animation.
[myWebView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat: #"window.scrollTo(0,%i);",414*self.initialScrollPosition]];
Everything going right, but on problem that I am facing is as follows.
Whenever User/I tap on the status bar of iPhone, WebView Bydefault scrolls to top.
This should not be done.
Is it possible to prevent inbuilt functionality ?
I know one of the option is as follows.
((UIScrollView *)[[myWebView valueForKey:#"_internal"] valueForKey:#"scroller"]).scrollsToTop = NO;
But is it valid to do ?

You can add a very tiny UIScrollView in the window. Then tapping the status bar won't scroll the web view to top.

A more straightforward way to do this would be to set the scrollsToTop property of the UIScrollView in the WebView to NO.
for(UIView *view in [myWebView subviews]) {
if([view isKindOfClass:([UIScrollView class])]) {
[(UIScrollView *)view setScrollsToTop:NO];
}
}
I have tested this on iOS 4.0 and 4.3 (iOS 5 seems to not need this).
adapted from this.

Related

How do I remove the iPhone KeyBoard toolbar border?

I am using the following code to remove the toolbar from the iPhone keyboard when it is displayed.
- (void) keyboardDidShowNotification:(NSNotification *)aNotification {
NSArray *array = [[UIApplication sharedApplication] windows];
for (UIWindow* wind in array) {
for (UIView* currView in wind.subviews) {
if ([[currView description] hasPrefix:#"<UIPeripheralHostView"]) {
for (UIView* perView in currView.subviews) {
if ([[perView description] hasPrefix:#"<UIWebFormAccessory"]) {
[perView removeFromSuperview];
}
}
}
}
}
}
This is removing the toolbar like I want but it is still leaving a 1px border above where the toolbar use to be. How do I remove that as well?
Also this only appears to be an issue on iPhone Retina displays. iPhone 3GS and iPad Retina do not have it.
Seems to be a bug in removeFromSuperView. I had the same problem when adding a toolbar as an input accessory view to some pickers for inline editing. Calling 2x removeFromSuperView left the border.
Using [self.view endEditing:YES] when closing the picker helped to clean up the picker and the accessory view attached to it, with no border. Perhaps this can point you into the right direction?

UIWebView Scrolling

I load an HTML form in my UIWebView and it so happens that my UIWebView starts from the middle of the view and extends. I have to lock this webView from scrolling and put it on top of a scrollView to allow scrolling. The webView shouldn't scroll internally. I have tried this
[[webView.subviews objectAtIndex:0] setScrollEnabled:NO];
but I am not able to stop the webView from scrolling internally when I load a form in it that has textFields clicking on which brings up the keyboard. When I load plaintext, I am able to get the desired behavior. I want to stop the webView from autoscrolling and handle the scrolling myself using the scrollView that lay beneath the webView. It might not make sense to most of you that I am reinventing the wheel but the requirement is such.
Can anybody suggest what to do?
You can try,
for (id subview in webView.subviews)
if ([[subview class] isSubclassOfClass: [UIScrollView class]])
if([subview respondsToSelector:#selector(setScrollingEnabled:)]) [subview performSelector:#selector(setScrollingEnabled:) withObject:NO];
or you need to stop bouncing of the webview you can try this.
for (id subview in webView.subviews)
if ([[subview class] isSubclassOfClass: [UIScrollView class]])
((UIScrollView *)subview).bounces = NO;
Hope this helps.
Try running this after the webview has loaded (i.e. in the proper delegate method):
[webView stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('body')[0].style.overflow='hidden'"]
If you have access to the HTML, you could also just set the correct style on the body element:
body { overflow: hidden; }
If you do either of these, you need to make sure that you make the UIWebView tall enough to display everything. You can get the height by running this (also after the webview has loaded):
CGFloat height = [webView stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight"]

How do I make UIWebView scroll to the top?

Is there a way to make a UIWebView scroll to the top when I touch say a UISearchView within the same viewController (without using Javascript).
Something like this:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[myWebView scrollToTop]; //pseudocode
}
In other words, what happens when I touch the top bar can also happen programmatically.
CGPoint top = CGPointMake(0, 0); // can also use CGPointZero here
[myWebView.scrollView setContentOffset:top animated:YES];
(Note that if you have set myWebView.scrollView.contentInset.top you will want to take that into account instead of just scrolling to CGPointZero.)
Here's a really ugly, terrible way to do this. I'm answering this to show you what never to do.
for (UIView *subview in webView.subviews)
{
if ([subview isKindOfClass:[UIScrollView class]])
[(UIScrollView*)subview setContentOffset:CGPointZero animated:YES];
}
If you don't want to use JavaScript there's no public API method to do this. UIWebViews don't inherit from scroll views, so you can't use any of the usual methods. As you've figured out, it's possible to do with JavaScript. You can try to find the actual scroll view in the UIWebView, but it's all undocumented and not really a good thing to do in a production app.
Update - as of iOS 5 you can now get direct access to a web view's UIScrollView - see Reconquistador's answer for more information.
Scroll the UIWebView by calling JavaScript through Objective-C:
NSString *script = #"scrollTo(0, 0)";
[webView stringByEvaluatingJavaScriptFromString:script];
For smooth scrolling, use a library like jQuery:
NSString *script = #"$('html, body').animate({scrollTop:0}, 'slow')";
[webView stringByEvaluatingJavaScriptFromString:script];
Access the UIWebView's scrollview and set YES to method scrollsToTop;
WebView.scrollView.scrollsToTop = YES;
Hope this helps!
Swift 3.x
webView.scrollView.setContentOffset(CGPoint.zero, animated: true)
I don't believe you will find any officially supported method to do what you are wanting.
This works for me:
CGPoint topOffset = CGPointMake(0, 0);
//[scrollView setContentOffset: topOffset animated: YES];
[[[webView subviews] lastObject] setContentOffset:topOffset animated:YES];
Where webView is the subclass of the UIWebView, of course.
why not just touch the status bar of your device. for all the scrollView based controls, tableView, webView, scrollView, there is a :
The scroll-to-top gesture is a tap on the status bar; when this property is YES, the scroll view jumps to the top of the content when this gesture occurs. The default value of this property is YES.
Displaying a PDF in a UIWebView, I found you can jump to the top simply by reloading the document.

How to reset UIWebView's zoom? I'm already using scalesPagesToFit = YES;

I've been looking for the past week for the answer to this question.
I have a UIWebView, inside of a UIScrollView. Everything works great, but I want the content of the UIWebView to reset its zoom, when the orientation changes.
In the HTML inside the UIWebView, I set the width of the viewport (w/ a meta tag) to "device-width" and then on the Obj-C side, I set the scalesPagesToFit = YES;
I've tried resetting the zoom with javascript; by replacing the meta tags in runtime; reloading; accessing the UIScrollView inside of the UIWebView; etc...
but with no success.
Any of you gods know a workaround?
The only one I can think off is to recreate the UIWebViews every time we change the orientation, but that makes them flash to white whilst rendering content, which looks terrible :(
Any thoughts?
Many thanks,
Andre
I'm just guessing here and haven't tried, but AFAIK a UIWebView has a UIScrollView child. So one should be able to do:
for (UIScrollView *scroll in [myWebView subviews]) {
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:#selector(setZoomScale:)])
[scroll setZoomScale:1.0];
}
On iOS 5+ you have access to scrollView.
Just do:
[webView.scrollView setZoomScale:1.0];
If you want to do it programmatically this is the only way I could find to accomplish it: (specify your own sizes if you wish, i was attempting to zoom out after typing into a form field)
UIScrollView *sv = [[webViewView subviews] objectAtIndex:0];
[sv zoomToRect:CGRectMake(0, 0, sv.contentSize.width, sv.contentSize.height) animated:YES];
Update:
Downscaling wasn't working properly when using
[[[webView subviews] lastObject] setZoomScale:0.25];
The quality of the images being downscaled on the page was awful. Doing:
[[[webView subviews] lastObject] setZoomScale:0.25 animated:YES];
Fixed it. So that last line is the one you could use.
webView was subclassed of a UIWebView which lies on some IB file. I didn't use the Viewport at all. I find that one should pick by either doing this from the Cocoa Touch side or use JS.
I used:
webView.scalesPageToFit = YES;
I wonder if there's a way of resetting the scalesPageToFit.
Adapting from Captnwalker1's answer, I came up with this:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if(toInterfaceOrientation ==UIInterfaceOrientationPortrait||toInterfaceOrientation==UIInterfaceOrientationMaskPortraitUpsideDown)
{
currentScrollView = [[webView subviews] objectAtIndex:0];
[currentScrollView zoomToRect:CGRectMake(0, 0, currentScrollView.contentSize.width, currentScrollView.contentSize.height) animated:NO];
}
else
{
currentScrollView = [[webView subviews] objectAtIndex:0];
[currentScrollView zoomToRect:CGRectMake(0, 0, currentScrollView.contentSize.width, currentScrollView.contentSize.height) animated:NO];
}
}
So load your webview image, and the image will reset it's size when rotated.

UIWebView pagination

I have a large html content to render in a UIWebView, I want to display the content in pages just like a book and the user uses buttons to navigate the pages. Is there any way to calculate the height of html content that fits in the webview without scrolling?
If anyone comes around, in iOS7 and more you can just do :
self.webview.paginationBreakingMode = UIWebPaginationBreakingModePage;
self.webview.paginationMode = UIWebPaginationModeLeftToRight;
for (id subview in self.webView.subviews)
{
if ([[subview class] isSubclassOfClass:[UIScrollView class]])
{
((UIScrollView *)subview).pagingEnabled = YES;
break;
}
}