I created a bare bones iPhone app with a UIWebView (Scales Page to Fit = YES, shouldAutorotateToInterfaceOrientation = YES) and loaded a webpage, e.g. https://stackoverflow.
- (UIScrollView *)findScrollViewInsideView:(UIView *)view
{
for(UIView *subview in view.subviews){
if([subview isKindOfClass:[UIScrollView class]]){
return (UIScrollView *)subview;
}
UIScrollView *foundScrollView = [self findScrollViewInsideView:subview];
if (foundScrollView){
return foundScrollView;
}
}
return nil;
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
switch (self.interfaceOrientation){
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
{
UIScrollView *webViewScrollView = ([self.webView respondsToSelector:@selector(scrollView)])
? self.webView.scrollView
: [self findScrollViewInsideView:self.webView];
[webViewScrollView setZoomScale:1.01f animated:YES];
}
break;
default:
break;
}
}
try this code, it insignificantly changes zoom level (1.01) to allow UIWebView increase content size in landscape mode
findScrollViewInsideView: method added to support ios4
I found something that worked for me. The problem is that when uiwebview changes its orientation web contents are zoommed to fit with viewport. But zoomscale parameter of scrollview subview is not updated correctly (nor are updated minimumZoomScale nor maximumZoomScale
Then we need to do it manually at willRotateToInterfaceOrientation
:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
CGFloat ratioAspect = webview.bounds.size.width/webview.bounds.size.height;
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
case UIInterfaceOrientationPortrait:
// Going to Portrait mode
for (UIScrollView *scroll in [webview subviews]) { //we get the scrollview
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:@selector(setZoomScale:)]){
scroll.minimumZoomScale = scroll.minimumZoomScale/ratioAspect;
scroll.maximumZoomScale = scroll.maximumZoomScale/ratioAspect;
[scroll setZoomScale:(scroll.zoomScale/ratioAspect) animated:YES];
}
}
break;
default:
// Going to Landscape mode
for (UIScrollView *scroll in [webview subviews]) { //we get the scrollview
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:@selector(setZoomScale:)]){
scroll.minimumZoomScale = scroll.minimumZoomScale *ratioAspect;
scroll.maximumZoomScale = scroll.maximumZoomScale *ratioAspect;
[scroll setZoomScale:(scroll.zoomScale*ratioAspect) animated:YES];
}
}
break;
}
}
Hope this helps!
On rotation, try setting the scrollView zoomScale to 0. See my full answer here: UIWebView content not adjusted to new frame after rotation
So apparently I didn't use the solution by M Penades in the end (and forgot to update this post! sorry).
What I did was to resize the entire document (and change my font-size to keep things proportionate). That apparently fixed the issue.
However, my UIWebView is only for loading my own HTML & CSS from the iOS filesystem - if you're building a general purpose web browser, this trick may not work as well.
ViewController.m
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
case UIInterfaceOrientationPortrait:
if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)) {
[webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'ppad'"];
} else {
[webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'pphone'"];
}
break;
default:
if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)) {
[webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'lpad'"];
} else {
[webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'lphone'"];
}
break;
}
}
And app.css
html>body.pphone { font-size:12px; width: 980px; }
html>body.lphone { font-size:18px; width: 1470px; }
html>body.ppad { font-size:12px; width: 768px; }
html>body.lpad { font-size:15.99999996px; width: 1024px; }
Gist at https://gist.github.com/d6589584944685909ae5
I am posting this because i have also faced the same problem and here i am following the M Penades
Approach.M Penades
's Answer woks good only for case if user does not Skew(pinch Out) the Webview then rotate the device and repeat this process .then Content Size of UiwebView gets reduce gradually. so that was the issue came in M Penades
Answer. so I have fixed that issue too and my code is as below.
1) For This I set the Pinch Gesture so that when User Skew The UIwebView could check the Scaled size of UIwebView.
//One This Please import The UIGestureRecognizerDelegate
Protocol in '.h file'
//call below method in ViewDidLoad Method for setting the Pinch gesture
- (void)setPinchgesture
{
UIPinchGestureRecognizer * pinchgesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(didPinchWebView:)];
[pinchgesture setDelegate:self];
[htmlWebView addGestureRecognizer:pinchgesture];
[pinchgesture release];
// here htmlWebView is WebView user zoomingIn/Out
}
//Allow The allow simultaneous recognition
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Returning YES is guaranteed to allow simultaneous recognition. returning NO is not guaranteed to prevent simultaneous recognition, as the other gesture's delegate may return YES
-(void)didPinchWebView:(UIPinchGestureRecognizer*)gestsure
{
//check if the Scaled Fator is same is normal scaling factor the allow set Flag True.
if(gestsure.scale<=1.0)
{
isPinchOut = TRUE;
}
else// otherwise Set false
{
isPinchOut = FALSE;
}
NSLog(@"Hello Pinch %f",gestsure.scale);
}
If User Hase Pinch In/Out The Web View in that Case Just Set THat Zooming Factor . SO that WebView Can Adjust Its ContentSize as Oreintaion Changed.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
//Allow the Execution of below code when user has Skewed the UIWebView and Adjust the Content Size of UiwebView.
if(isPinchOut){
CGFloat ratioAspect = htmlWebView.bounds.size.width/htmlWebView.bounds.size.height;
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
case UIInterfaceOrientationPortrait:
// Going to Portrait mode
for (UIScrollView *scroll in [htmlWebView subviews]) { //we get the scrollview
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:@selector(setZoomScale:)]){
scroll.minimumZoomScale = scroll.minimumZoomScale/ratioAspect;
scroll.maximumZoomScale = scroll.maximumZoomScale/ratioAspect;
[scroll setZoomScale:(scroll.zoomScale/ratioAspect) animated:YES];
}
}
break;
default:
// Going to Landscape mode
for (UIScrollView *scroll in [htmlWebView subviews]) { //we get the scrollview
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:@selector(setZoomScale:)]){
scroll.minimumZoomScale = scroll.minimumZoomScale *ratioAspect;
scroll.maximumZoomScale = scroll.maximumZoomScale *ratioAspect;
[scroll setZoomScale:(scroll.zoomScale*ratioAspect) animated:YES];
}
}
break;
}
}
}
This Works perfectly for even user skew the UIWebView.
I've tried the solution from M Penades and this seems to work for me as well.
The only issue that I'm experiencing is that when running this on a 3Gs the rotation is unfortunately not very smooth.
I'm therefore now using a different approach:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
CGFloat scale = browserWebView.contentScaleFactor;
NSString *javaStuff = [NSString stringWithFormat:@"document.body.style.zoom = %f;", scale];
[browserWebView stringByEvaluatingJavaScriptFromString:javaStuff];
}
Best Regards,
Ralph