Abs
Abs

Reputation: 57966

HTML Content fit in UIWebview without zooming out

I am making use of the UIWebView to render some HTML. However, although the width of my webview is 320 my HTML is still shown full width and can be scrolled horizontally.

I want to achieve the same thing the native mail application achieves which is it fits all content within that width without zooming out - how does the native mail application render HTML like this?

Update

I thought making use of the viewport meta tag will help, but I couldn't get this to work.

This is what is happening:

enter image description here

As you can see the content does not fit the device width. I've tried so many combinations of viewport meta tag. The below is an example of what happens when I try Martins suggestion.

Original HTML is can be found here.

The way this HTML is rendered by the native mail application is like so.

Upvotes: 55

Views: 81484

Answers (8)

mprivat
mprivat

Reputation: 21912

Here's what you do:

In your UI controller that owns the web view, make it a UIWebViewDelegate. Then where you set the URL to load, set the delegate as the controller:

NSString *urlAddress = @"http://dl.dropbox.com/u/50941418/2-build.html";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];  
webView.delegate = self;

And finally implement the webViewDidFinishLoad: to correctly set the zoom level:

This option will applicable from iOS 5.0 and >

- (void)webViewDidFinishLoad:(UIWebView *)theWebView
{
  CGSize contentSize = theWebView.scrollView.contentSize;
  CGSize viewSize = theWebView.bounds.size;

  float rw = viewSize.width / contentSize.width;

  theWebView.scrollView.minimumZoomScale = rw;
  theWebView.scrollView.maximumZoomScale = rw;
  theWebView.scrollView.zoomScale = rw;  
}

Option B, you can try to alter the HTML (this example does the job but is less than perfect from an HTML parsing standpoint. I just wanted to illustrate my point. It does work for your example, and probably most cases. The inset of 40 can probably be detected programmatically, I didn't try to research that.

NSString *urlAddress = @"http://dl.dropbox.com/u/50941418/2-build.html";
NSURL *url = [NSURL URLWithString:urlAddress];

NSString *html = [NSString stringWithContentsOfURL:url encoding:[NSString defaultCStringEncoding] error:nil];
NSRange range = [html rangeOfString:@"<body"];

if(range.location != NSNotFound) {
  // Adjust style for mobile
  float inset = 40;
  NSString *style = [NSString stringWithFormat:@"<style>div {max-width: %fpx;}</style>", self.view.bounds.size.width - inset];
  html = [NSString stringWithFormat:@"%@%@%@", [html substringToIndex:range.location], style, [html substringFromIndex:range.location]];
}

[webView loadHTMLString:html baseURL:url];

Upvotes: 133

Omar N Shamali
Omar N Shamali

Reputation: 773

i solved the issue by unticking "scales page to fit" enter image description here

Upvotes: 0

nrx
nrx

Reputation: 369

You may generate an NSAttributedString from HTML (do it on background):

@implementation NSAttributedString (Utils)

+ (void)parseHTML:(NSString *)html withCompletion:(void (^)(NSAttributedString *completion, NSError *error))completion
{
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        NSError * __autoreleasing *error = nil;
        NSAttributedString *result = [[NSAttributedString alloc] initWithData:[html dataUsingEncoding:NSUTF8StringEncoding]
                                                                      options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                                                                NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
                                                           documentAttributes:nil error:error];
        NSError *safeError = (error != nil) ? *error : nil;
        dispatch_sync(dispatch_get_main_queue(), ^(void){
            completion(result, safeError);
        });
    });
}

@end

And show it through UITextView instance:

[NSAttributedString parseHTML:htmlString withCompletion:^(NSAttributedString *parseResult, NSError *error) {
        bodyTextView.attributedText = parseResult;
}];

Some layout features, though, may corrupt with this approach.

Upvotes: 0

Werner Altewischer
Werner Altewischer

Reputation: 10474

@implementation UIWebView (Resize)

- (void)sizeViewPortToFitWidth {
    [self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.querySelector('meta[name=\"viewport\"]').setAttribute('content', 'width=%d;', false); ", (int)self.frame.size.width]];
}

@end

Upvotes: 1

aashish tamsya
aashish tamsya

Reputation: 4959

Swift 3:

Use this extension to resize contents of webview according to size of a webview.

extension UIWebView {
    ///Method to fit content of webview inside webview according to different screen size
    func resizeWebContent() {
        let contentSize = self.scrollView.contentSize
        let viewSize = self.bounds.size
        let zoomScale = viewSize.width/contentSize.width
        self.scrollView.minimumZoomScale = zoomScale
        self.scrollView.maximumZoomScale = zoomScale
        self.scrollView.zoomScale = zoomScale
    }
}

How to invoke?

webViewOutlet.resizeWebContent()

Upvotes: 1

Martin
Martin

Reputation: 12215

Typically, you should use the viewport meta tag. But its use is very erratic, mostly if you want a cross platform web page.

It also depends of what content and css you have.

For my iPhone homepage, which must auto-resize from portrait to lanscape, I use this :

<meta name="viewport" content="width=device-width; minimum-scale=1.0; maximum-scale=1.0; user-scalable=no">

If you need special resize, you can also use the event :

<body onorientationchange="updateOrientation();">

with the corresponding funciton in your javascript :

function updateOrientation() {
  if(Math.abs(window.orientation)==90)
      // landscape
  else
      // portrait   
}

EDIT :

Seeing you page source, it seems you made it with a web editor, don't you ?

Ok, I understand. Your main div has a width of 600px. The iphone screen resolution is 320x480. 600 > 320 so it exceeds the screen bounds.

Now, let's make some simple operations:

320 / 600 = 0.53
480 / 600 = 0.8

So you want to zoom out 0.5 times minimum and 0.8 times maximum. Lets change the viewport :

<meta name="viewport" content="width=device-width; minimum-scale=0.5; maximum-scale=0.8; user-scalable=no"> 

Upvotes: 6

Chris Livdahl
Chris Livdahl

Reputation: 4750

What worked for me was to select the UIWebView in Interface Builder and check the box that says "Scales Page To Fit":

enter image description here

Upvotes: 5

Denis
Denis

Reputation: 3353

Just add this:

webView.scalesPageToFit = YES;

Upvotes: 57

Related Questions