UIWebview resize height to fit content - iphone

I know this has been asked many times but I can not get it to work. In short my UIWebview pulls in some HTML which has a none fixed height (width always the same), I just want the height to change accordingly.
I have tried a number of fixes I have found online but my problem is the webview will change to the correct size but only for a brief second and then in flicks back to the original size.
I should point out that my this view is invoked by a segue, that is the only thing I can think is different! I am wondering if the code works but when the segue finishes it's crossfade, flip or whatever it then redraws the webview.
Here is my current code (as I say I have tried many fixes including the Java versions most of which do the same), I have also played with scalesPageToFit and srollEnabled plus a few of the ticks in the Storyboard.
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
NSLog(#"Starting Size : %f", headerWebView.frame.size.height);
headerWebView.scalesPageToFit = YES;
headerWebView.scrollView.scrollEnabled = NO;
CGRect frame = headerWebView.frame;
frame.size.width = frame.size.width; // I used this to test, I put 200 in and it changes then flicks back too
frame.size.height = 1;
headerWebView.frame = frame;
frame.size.height = headerWebView.scrollView.contentSize.height;
headerWebView.frame = frame;
NSLog(#"Finished Size : %f", headerWebView.frame.size.height);
}
The logs say;
Starting Size : 176.000000
Finished Size : 246.000000
Anyone got an idea as to why the Webview appears fine just long enough for me to notice and then "shrink" back?

Anyone got an idea as to why the Webview appears fine just long enough
for me to notice and then "shrink" back?
I would say that it appears fine because you are showing the changes as they are happening. Why not hide the web view at some earlier point in the view lifecycle or even in webViewDidFinishLoading? I am sharing my layout settings from IB in case that may provide further assistance. Please advise if this helps or whether additional information is needed. I am using springs and struts rather than auto layout. I would try these method to see if it works for you.
Hiding my web view data loads prevents users from seeing anything until all of my settings/data are in place.
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[webView setAlpha:0];
[webView loadData:[dataString dataUsingEncoding:NSUTF8StringEncoding] MIMEType:#"text/html" textEncodingName:#"UTF-8" baseURL:baseURL];
[UIView animateWithDuration:0.1 animations:^{
[webView setAlpha:1.0];
} completion:nil];

Related

UIWebview delay to load text while scrolling?

I have add html file to load inside UIWebview and its working fine.
Then (UIWebview) scrolling faster delay to load text, its appear white background while scrolling faster. I want to remove the white background while scrolling faster.
Is it possible to load UIActivityIndicatorView at the timw, please hlep me
Thanks in Advance
Because event tracking in UIScrollview blocks the main thread.
You can try to force scrollView end scrolling(or decelerating) before another web action.
I played with your original solution a bit, and this seems to work just fine. I think you almost had it, but you were just offsetting the rect that you used too much, and forgot that you could just scroll the rect straight back to the original rect.
The generalized solution for any scrolling action is this:
- (void)killScroll
{
CGPoint offset = scrollView.contentOffset;
offset.x -= 1.0;
offset.y -= 1.0;
[scrollView setContentOffset:offset animated:NO];
offset.x += 1.0;
offset.y += 1.0;
[scrollView setContentOffset:offset animated:NO];
}
[Edit] As of iOS 4.3 (and possibly earlier) this also appears to work
- (void)killScroll
{
CGPoint offset = scrollView.contentOffset;
[scrollView setContentOffset:offset animated:NO];
}
I think I found the problem. It looks like NSURLRequestReturnCacheDataElseLoad and NSURLRequestReturnCacheDataDontLoad is broken on the iPhone. When a NSCachedURLResponse is returned from the cache and it contains HTTP headers indicating that the content has expired (e.g. Expires, Cache-Control etc), the cached response is ignored and the request is made to the original source.
The solution is as follows:
Implement your own subclass of NSHTTPURLResponse which allows you to modify the allHeaderFields dictionary.
Implement your own NSURLCache, override cachedResponseForRequest: and return a new NSCachedURLResponse containing an instance of your NSHTTPURLResponse subclass with the relevant "expiry" HTTP headers stripped.

Change the height of the UIWebView according to the content size

I am creating a webview to display some text in my app.
CGRect frame = CGRectMake(lblContent.frame.origin.x,
lblContent.frame.origin.y,
lblContent.frame.size.width,
lblContent.frame.size.height);
NSString *htmlText = HTML_DIV_TAG;
htmlText = [htmlText stringByAppendingFormat:#"%#%#", _artistDetail.strContent, #"</div>"];
htmlText = [htmlText stringByReplacingOccurrencesOfString:#"''" withString:#"'"];
UIWebView *webView = [[UIWebView alloc]initWithFrame:frame];
[webView loadHTMLString:htmlText baseURL:nil];
webView.scrollView.bounces = NO;
[self addSubview:webView];
This is the set of codes that i put it in to my app.
But need to adjust the height of the web view according to the content size.
If you set webview.delegate = self you can add the UIWebViewDelegate protocol method webViewDidFinishLoad: and invoke a small bit of javascript to determine the height:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *output = [webview stringByEvaluatingJavaScriptFromString:#"document.body. scrollHeight;"];
NSLog(#"height: %#", output);
}
Another method would be to determine the webView's scrollView contentSize in this method, since that should fit the entire website by the time this method is called.
The only problem with this method, is that this method is called when the page finishes loading. Images are handled differently, which means that the webView might change sizes due to images that finish loading.
try -
float height= [iText sizeWithFont:[UIFont fontWithName:#"FontSpecifiedInTheHtmlText" size: -SpecifiedInHTMLText- constrainedToSize:CGSizeMake(320, 100000)lineBreakMode:UILineBreakModeWordWrap].height;
after u get the height of the content text, u can set the frame/bounds of the WebView.
You may want this:
[webView.scrollView setContentInset:UIEdgeInsetsMake(0, 0, 20, 0)];
UIWebview is scrollable. So when you open a page in UIWebview u need not adjust the height according to the content of the page. You can see all the content by scrolling the UIWebView. You should check that user interaction is enabled for your webview.

How do I make a UIWebView's content adjust to the iPhone screen size?

I know there a lot of similar questions to this, but I didn't find any that helped me out. I made a webView that displays a url that has a survey on it, but the content isn't shrinking to the size of the screen. Can somebody tell me what I need to write to just get the content to shrink to the screen size, and where I put it? Any help would be greatly appreciated.
- (void)viewDidLoad
{
NSString *website =#"http://www.nameofwebsite.com";
NSURL *url = [NSURL URLWithString:website];
NSURLRequest *requestURL =[NSURLRequest requestWithURL:url];
webView.scalesPageToFit = YES;
webView.autoresizesSubviews = YES;
[webView loadRequest:requestURL];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
The statement
webView.scalesPageToFit = YES;
should size the web page to fit the size of the UIWebView. The user then has the option to zoom in and out of the page. Your problem might be because the webview is not located properly. If your view controller's view fits the screen entirely, add this to your code.
webView.frame=self.view.bounds;
write this
webView.frame = self.view.frame;
it will make the webview to iphone screen size
Try using auto layout:Select your web view in your storyboard then set auto layout to all 4 constraints.

Zooming on UIWebView

I have a UIWebView which I'm using to display a variety of content, sometimes HTML and sometimes PDF/Powerpoint/etc (which is all seemingly handled by the same underlying control).
What I want to do is harness the underlying UIScrollView (a subview of the UIWebView) to capture the exact perspective of the scroll view and recreate the scroll position in another UIWebView, thus keeping them both in sync.
The problem that I'm having is that the zoomScale property of the UIScrollView is always 1.0 while displaying HTML content (though when displaying PDF content, zoomScale is correct).
I managed to find that the only place where I can get any inkling of the zoom scale of an HTML page is in the scrollViewDidEndZooming:withView:atScale: delegate method. I've found that the atScale: argument seems to provide a relative zoom scale, to what the zoom scale was before the zooming operation began. So for example when zooming in, that argument is >1, and when zooming out it is <1, and it seems to be a relative value between the two zoom scales rather than an absolute zoom scale).
What I've further found is that fundamentally, HTML and PDF content is handled by two different underlying views: there's UIWebBrowserView which handles HTML content, and UIWebPDFView to handle displaying of PDFs.
So in other words, when using a UIWebPDFView, the zoomScale property of the UIScrollView is completely reliable (e.g. 1.0 for zoomed-out, 2.4 for zoomed-in, for example). On the other hand, UIWebBrowserView is much more fiddly, and when asking the UIScrollView for its zoomScale, always returns 1.0, but when receiving the delegate callback, receives a scale value that is a relative value.
So my questions are:-
Is this a bug? (This behaviour is seen on both iOS 4 and 5 from what I've seen).
How can I get both the zoomScale (or some other property/properties) for both HTML and PDF content, and get it in such a way that the state can be duplicated and kept in sync with another UIWebView.
I'm not beholden to using zoomScale, so I'm open to other suggestions for how the scroll state of a UIWebView can be captured and reproduced on another UIWebView.
When loading HTML, and UIWebBrowserView is being used, you can use
zoomScale = 1.0 / webView.scrollView.minimumZoomScale
Of course this is assuming that you can reliably ensure that the minimum zoom of your HTML page is 1.0, since some pages can alter the minimum zoom using the "viewport" meta tag.
Have you tried this?
set scalesPageToFit=YES;
That's the most common way to deal with the problem i think. Setting that enables you to pinch and zoom UIWebView.I don't think you can actually zoom in/out UIWebView without that.
Now the zoom is going to be relative to whatever you're showing on your UIWebView. If it is a big table, it's not so close but it's a good start point if you're going to pinch for zoom in.
This Logic for zooming of UIWebView, no need to add UIWebView on UIScrollView
Well only problem with webView.scalesPageToFit=YES; is, it change initial content font size but I have got other option by my self, Its working very well for me.
Add <UIWebViewDelegate, UIScrollViewDelegate> to your .h file
Creation of your UIWebView.
self.mWebview = [[UIWebView alloc] init];
self.mWebview.delegate = self; /// set delegate method of UIWebView
self.mWebview.frame = CGRectMake(0, 35, self.view.bounds.size.width, self.view.bounds.size.height - 80); // set frame whatever you want..
[self.mWebview setOpaque:NO];
self.mWebview.backgroundColor = [UIColor clearColor];
[self.view addSubview:self.mWebview];
With load HTML file/content.
NSString* htmlString = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"File Name"ofType:#"html"] encoding:NSUTF8StringEncoding error:nil];
[self.mWebview loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
#pragma mark -
#pragma mark - Webview Delegate Methods
- (void) webViewDidFinishLoad:(UIWebView *)webView
{
webView.scrollView.delegate = self; // set delegate method of UISrollView
webView.scrollView.maximumZoomScale = 20; // set as you want.
webView.scrollView.minimumZoomScale = 1; // set as you want.
//// Below two line is for iOS 6, If your app only supported iOS 7 then no need to write this.
webView.scrollView.zoomScale = 2;
webView.scrollView.zoomScale = 1;
}
#pragma mark -
#pragma mark - UIScrollView Delegate Methods
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
self.mWebview.scrollView.maximumZoomScale = 20; // set similar to previous.
}
NOTE: I had to tested on Mac OS X - 10.9.3 with Xcode 5.1.1 and iOS version 6.1 and latter.
I hope this will helpful for you. :)
Unfortunately the only way I found to get the actual scale of the web content in a UIWebView is by accessing to a private member of the UIWebBrowserView : initialScale.
float initialScale = (access to [UIWebBrowserView initialScale])
float zoomScale = 1.0 / webView.scrollView.minimumZoomScale;
float actualScale = zoomScale * initialScale;
I am wondering if this can be done without accessing to private member.
This may be a little late but for those who need to determine whether the current UIWebView contains HTML. A method I wrote to determine this was below. I called this immediately after the webView has loaded
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if (!webViewIsHTMLHasBeenSet) {
webViewIsHTML = [self containsWebBrowserView];
NSLog(#"webViewIsHTML = %#",webViewIsHTML ? #"YES": #"NO");
}
}
- (BOOL)containsWebBrowserView {
BOOL result = NO;
for (UIView * WVSubview in [webView.scrollView subviews]) {
if ([NSStringFromClass([WVSubview class]) isEqualToString:#"UIWebBrowserView"]) {
result = YES;
webViewIsHTMLHasBeenSet = YES;
return result;
}
}
webViewIsHTMLHasBeenSet = YES;
return result;
}
just simply set,
scalesPageToFit=YES for pich zoom on a UIWebView

iPhone SDK - UIWebView has a grey box over it

Sometimes, my UIWebView will have a grey box over part or all of the content. I can't make heads or tails of why it's happening. It happens regularly for certain content.
Thanks!
--Update--
It seems to occur when the webview is not immediately viewable on the screen -- ie i've got a scrollview, and the webview is below the fold.
--Update #2--
When I bring the content above the fold, it loads fine most of the time. There are still instances when the grey box is still showing up. The weird part is if i double-tap it, it finishes loading the content just fine. bizarre
--Update #3--
Okay, so it seems to be that if my uiwebview has a height greater than 1000px, a grey box appears on the rest of the content below 1000px. A double-tap reveals the actual content.
All UIViews have a size limit of 1024x1024 pixels. This is stated at the end of the Overview section of the UIView documentation.
If your web view must have more than 1024px of content, you will have to take it out of the parent scroll view and let it manage scrolling on its own.
Nudging the UIScrollView in the UIWebView it fixes this for me:
[UIScrollView *webScroller= [[webView subviews] lastObject];
[webScroller setContentOffset:CGPointMake(0,1) animated:NO];
[webScroller setContentOffset:CGPointMake(0,0) animated:NO];
I have been dealing with this glitch as well, and have opened a bug report at apple.
I would have commented above, but I don't have the 50 rep yet.
For anyone else encountering this glitch, send them a report, I included a full project demonstrating it, with a few screenshots from another app I am working on.
The more bug reports they get on a topic, the more likely they are to address it, apparently.
https://bugreport.apple.com/
I've got the same problem. I put a UIWebView inside a big TableViewCell (>1024px) and when I scroll to the bottom of the cell, there is this grey box.
But, if I put a UILabel (also with a big size > 1024px), there is no grey box. So I think this has nothing to do with a max height of a UIView (BTW I can't find anything about this so called 1024 max height). I think it's more a UIWebView issue.
The solution for me is to reload the content of the webview when the grey box appears. Actually, I just have a HTMLString to load so I call [webview loadHTMLstring:] again, and the grey box disappear.
Hope that will help
I found a very intersting post about that, it solved the problem for me :
link ttp://pinchzoom.com/blog/items/view/1386/one-of-the-problems-with-the-uikit-at-the-moment-is-an-issue-embedding-a-uiwebview-within-a-table
Hope that helps
I've used stringByEvaluatingJavaScriptFromString plus moving UIWebView origin.
Design overview: I had a set of controls(UIImage in this example) above(I mean frame.origin.y) UIWebView. So, layout was:
UIView
UIScrollView
UIImageView
UIWebView
Since UIWebView doesn't support scrolling in such hierarchy I've rearrange it like:
UIView
UIScrollView
UIImageView
UIWebView
My view controller is delegate for UIWebViewDelegate and UIScrollViewDelegate.
Then,
- (void)viewDidLoad
{
// set delegates
self.scrollView.delegate = self;
self.webView.delegate = self;
// store original UIWebView position in ivar
webViewPosY = self.webView.frame.origin.y;
// load html into UIWebView
[self.webView loadHTMLString:someHTML baseURL:nil];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
// get UIWebView size and store in ivar
webSize = [self.webView sizeThatFits:CGSizeMake(1.0,1.0)];
// set proper content height for UIScrollView
CGSize contentSize = self.scrollView.contentSize;
contentSize.height = webViewPosY + webSize.height;
self.scrollView.contentSize = contentSize;
// set UIWebView's frame height same as UIScrollView has
CGRect wf = self.webView.frame;
wf.size.height = self.scrollView.frame.size.height;
self.webView.frame = wf;
}
// scrolling logic:
// 1. if origin of UIWebView > 0 then move UIWebView itself
// 2. if origin of UIWebView == 0 then scroll with javascript
// 3. if origin is 0 and whole html is scrolled then move UIWebView again(this happens to support scroll "bouncing", or if you have some views below UIWebView
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat scrollPosY = self.scrollView.contentOffset.y;
// (1) and (2) ifs
// how much to move UIWebView
CGFloat scrollOriginY = (scrollPosY >= webViewPosY) ? webViewPosY : scrollPosY;
// how much to scroll via JS
CGFloat scrollJSY = scrollPosY - scrollOriginY;
// (3) if
if ( scrollPosY > (webSize.height - scrollViewSize.height + webViewPosY ) )
scrollOriginY += scrollPosY - (webSize.height - scrollViewSize.height + webViewPosY);
// scroll with JS
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"document.body.scrollTop = %f;", scrollJSY]];
// move UIWebView itself
CGRect wf = self.webView.frame;
wf.origin.y = webViewPosY - scrollOriginY;
self.webView.frame = wf;
}
This works just fine for me.
I ran into the same issue when dynamically resizing a UIWebView. Here's what worked for me:
#define LAYER_FOR(ui) [(ui) layer]
#define FRAME_FOR(ui) [LAYER_FOR((ui)) frame]
#define SET_FRAME_FOR(ui, frame) [LAYER_FOR((ui)) setFrame: (frame)]
+ (void) setHeightTo: (CGFloat *) height_ptr forView: (UIView *) a_view {
CGFloat height = *height_ptr;
CGRect existing_frame = [[a_view layer] frame];
existing_frame.size.height = height;
// need to reassign the same frame !?
NSLog(#"setting text view: %# to height: %f", a_view, (float) height);
SET_FRAME_FOR(a_view, existing_frame);
}
+ (void) resizeWebView: (UIWebView *) webView {
NSString *js = #" \
var __html_element = document.getElementsByTagName('html')[0]; \
var __height_string = document.defaultView.getComputedStyle(__html_element, null).getPropertyValue('height'); \
__height_string.replace('px', ''); \
";
NSString *heightString = [webView stringByEvaluatingJavaScriptFromString: js];
float height = [heightString floatValue];
if (height != UI_VIEW_HEIGHT(webView)) {
[self setHeightTo: &height forView: webView];
// resize scrollView inside webview to the same height
UIScrollView *webScroller = [[webView subviews] lastObject];
[self setHeightTo: &height forView: webScroller];
}
}
I called this code from webview's delegate 'webViewDidFinishLoad:' method.
Basically, the trick is to resize the webScroller inside webview.
Thanks to Padraig for the suggestion to nudge the webview's subview (the scrollview).