UIWebView with just an image that should fit the whole view

13,786

Solution 1

UPDATE : I found a better way to do this with Javascript, no need to set sizeToFit

NSString *htmlString = [NSString stringWithFormat:
                        @"<html>"
                        "<head>"
                        "<script type=\"text/javascript\" >"
                        "function display(img){"
                        "var imgOrigH = document.getElementById('image').offsetHeight;"
                        "var imgOrigW = document.getElementById('image').offsetWidth;"
                        "var bodyH = window.innerHeight;"
                        "var bodyW = window.innerWidth;"
                        "if((imgOrigW/imgOrigH) > (bodyW/bodyH))"
                        "{"
                        "document.getElementById('image').style.width = bodyW + 'px';"
                        "document.getElementById('image').style.top = (bodyH - document.getElementById('image').offsetHeight)/2  + 'px';"
                        "}"
                        "else"
                        "{"
                        "document.getElementById('image').style.height = bodyH + 'px';"
                        "document.getElementById('image').style.marginLeft = (bodyW - document.getElementById('image').offsetWidth)/2  + 'px';"
                        "}"
                        "}"
                        "</script>"                         
                        "</head>"
                        "<body style=\"margin:0;width:100%;height:100%;\" >"
                        "<img id=\"image\" src=\"%@\" onload=\"display()\" style=\"position:relative\" />"
                        "</body>"
                        "</html>",url
                        ];


[webView loadHTMLString:htmlString baseURL:nil];

Old version (doesn't work well though)

I don't like answering my own question, but I'm so excited I discovered the solution to this issue !

So basically what you need to do this :

  1. Init the view with it's real final desired frame :

    webView = [[UIWebView alloc] initWithFrame:_desiredFrame];
    
  2. Add a viewport property, and set the image width to this property (I choose 1200px so it's bigger than all possible devices, and will not stretch the content twice) The script with the ontouchstart is just to prevent scrolling from the view and being approved by Apple.

    NSString *html = [NSString stringWithFormat:@"<html><head>"
    "<script>document.ontouchstart = function(event) { event.preventDefault();  }</script>"
    "<meta name=\"viewport\" content=\"width=1200\"/>"
    "</head>"
    "<body style=\"margin:0;padding:0;\">"
    "<img style=\"width:1200px\" src=\"%@\" />"
    "</body>"
    "</html>",imageName];
    
  3. Tell the view to scale it's content to fit :

    webView.scalesPageToFit = YES;
    

Then you can load your stuff ! I don't know how to do if you need to resize the view programatically later, I might have to do it and will post here if I figure out how. If you know how, or have a better solution, I'd appreciate the solution

Solution 2

One nice and simple solution is to put this code on your HTML <head> tag:

<meta name="viewport" content="width=device-width,minimum-scale=1.0, maximum-scale=1.0" />

Here you can define zoom scales and widths.

Share:
13,786
Julien
Author by

Julien

Updated on June 04, 2022

Comments

  • Julien
    Julien almost 2 years

    So the issue I'm having now is with UIWebViews displaying a single image. What I'd like is the image to be reduced if it doesn't fit the place, and keep it's original size if not. So here is how I do it (in a UIViewController):

    - (void)viewDidLoad {
        [super viewDidLoad];
        UIWebView *webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 80)];
        NSString *path =[[NSBundle mainBundle] bundlePath];
        NSURL *baseUrl =[NSURL fileURLWithPath:path];
    
        NSString *html = [NSString stringWithFormat:@"<html><head>"
    //THE LINE ABOVE IS TO PREVENT THE VIEW TO BE SCROLLABLE
            "<script>document.ontouchstart = function(event) { event.preventDefault();  }</script>"
            "</head><body style=\"text-align:center;margin:0;padding:0\">"
            "<img src=\"banner.gif\" />"
            "</body>"
            "</html>"];             
    
        webView.scalesPageToFit = YES;
        [webView loadHTMLString:html baseURL:baseUrl]; 
        [self.view addSubview:webView];
        [webView release];
    }
    

    This crops the image and makes the webview scrollable, which is not the desired behavior.

    So I started trying with some CSS int the image tag :

    "<img style=\"width:100%\" src=\"banner.gif\" />"
    

    or

    "<img style=\"max-width:100%\" src=\"banner.gif\" />"
    

    I don't know why, but 100% doesn't seem to be the width of the UIView, it's really small ! (the source image in the view is bigger than 320px, and here's the result :)

    Too Small Image

    So I tried seting the body's width :

            "</head><body style=\"width:100%;text-align:center;margin:0;padding:0\">"
            "<img style=\"width:100%\" src=\"banner.gif\" />"
    

    And what that does is just preventing the "text-align" property to work. I tried also removing the text-align, because if the width fits the view, it's unnecessary, but it still doesn't work. I also tried set an image size to the view's width, but it doesn't work on retina devices then… I tried to set a viewport to device-width, but it doesn't change.

    Any idea on how to do this ?

    Here is a little sample with 3 images I'd like to fit, in case you have time to have a look