Reputation: 57966
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?
I thought making use of the viewport meta tag will help, but I couldn't get this to work.
This is what is happening:
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
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
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
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
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
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
Reputation: 4750
What worked for me was to select the UIWebView in Interface Builder and check the box that says "Scales Page To Fit":
Upvotes: 5