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).
Related
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.
I've a UIScrollView of size (320,160). I'm adding some UIImageView into it, which are of size (213,160). The first UImageView starting from 54 (x) and so on, I've added a space of 5.0 in between each UIImageView. I've also enabled pagingEnable in IB & in coding. What my problem is its not properly working as per its property! When I scroll it should show me UIImageViews in each single page instead it showing me something like see screenshot I want output something like this see output screenshot
Where I'm doing wrong? I also having function of< (previous) & > (next) there to show images. I've asked one question yesterday which was I accepted however my requirement is little change and it won't become my solution. see my question.
Is there any special property that I've to set, or some logic I should implement? All examples I've checked and tried but I find that my requirement is some special. Point me! Thanks.
EDITED:
- (void) setImages
{
CGFloat contentOffset = 0.0f;
for (int i=0; i<[arrImgUrls count]; i++)
{
CGRect imageViewFrame = CGRectMake(contentOffset, 0.0f, 213, scrollImages.frame.size.height);
AsyncImageView *asyncImageView = [[AsyncImageView alloc] initWithFrame:imageViewFrame];
[asyncImageView.layer setMasksToBounds:YES];
NSString *urlImage = [arrImgUrls objectAtIndex:i];
NSURL *url = [NSURL URLWithString:urlImage];
[asyncImageView loadImageFromURL:url];
[scrollImages addSubview:asyncImageView];
contentOffset += asyncImageView.frame.size.width+increment;
[asyncImageView release];
}
scrollImages.contentSize = CGSizeMake([arrImgUrls count] * scrollImages.frame.size.width, scrollImages.frame.size.height);
scrollImages.pagingEnabled = YES;
scrollImages.clipsToBounds = NO;
}
-(IBAction)prevImage:(id)sender
{
_currentImage--;
[btnNext setEnabled:YES];
if (_currentImage==0)
{
[btnPrev setEnabled:NO];
[scrollImages setContentOffset:CGPointMake((_currentImage*imageWidth), 0) animated:YES];
return;
}
NSLog(#"previous:mult %d inc %d current %d",_currentImage*imageWidth,increment*_currentImage,_currentImage);
int nextImage=_currentImage+2;
[scrollImages setContentOffset:CGPointMake((((_currentImage*imageWidth)-(increment*_currentImage)))+(nextImage*increment), 0) animated:YES];
}
-(IBAction)nextImage:(id)sender
{
_currentImage++;
NSLog(#"next:mult %d inc %d current %d",_currentImage*imageWidth,increment*_currentImage,_currentImage);
[scrollImages setContentOffset:CGPointMake((_currentImage*imageWidth)+(increment*_currentImage), 0) animated:YES];
[btnPrev setEnabled:YES];
if (_imageCount-1 == _currentImage)
{
[btnNext setEnabled:NO];
}
}
Paging scroll views alway page multiples of their frame size. So in your example paging is always +320.
This behavior is good if you have content portions matching the frame of the scroll view.
What you have to do, is giving your scroll view a width of 213 and set its clipsToBounds property to NO.
After that your scroll view pages exactly how you want and you see what's left and right outside the frame.
Additionally you have to do a trick to make this left and right area delegate touches to the scroll view.
It's greatly explained in this answer.
You are forgetting to set scrollview content size.
make sure that you have set the content size to fit N number of images.
if you want to scrollview to scroll for 10 images with an image on each page
set scrollView contentSize as
[scrollView setContentSize:CGSizeMake(320 * 10,200)];
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
I have UIScroll that have uitextview inside it.
My apps look like this:
rootviewcontroller -> PhoneContentController (UIScrollView and PageControl) -> DetailController (UITextView, UIWebView, UILabel).
My Flow is like this:
Set UIScrollView default size -> call DetailController (calculate UITextView and other page inside it in viewDidLoad) -> PhoneContentController get the total height size from DetailController-> Change the height of UIScrollView
This is the code in PhoneContentController (loadSCrollViewWithPage):
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, [detailController.getTotalHeight]);
The code in Detail Controller (viewDidLoad):
summaryBlogParsed = [summaryBlogParsed stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[self.itemSummaryText setText:summaryBlogParsed];
CGRect frameTextView = self.itemSummaryText.frame;
frameTextView.size.height = self.itemSummaryText.contentSize.height;
self.itemSummaryText.frame = frameTextView;
This code in DetailController getTotalHeight:
CGRect cgRect = [[UIScreen mainScreen] bounds];
CGFloat scrollFrame = (cgRect.size.height/2) + itemSummaryText.frame.size.height;
return scrollFrame;
I can scroll the scrollview but the textview not load all of the string. like only half of it, but i can scroll down but with blank pages :(.
Anyone can help me?
Thank you
set content size of scroll view using this function.
-(void)setContentSizeOfScrollView:(UIScrollView*)scroll
{
CGRect rect = CGRectZero;
for(UIView * vv in [scroll subviews])
{
rect = CGRectUnion(rect, vv.frame);
}
[scroll setContentSize:CGSizeMake(rect.size.width, rect.size.height)];
}
after adding all controls to your scroll view call this function and pass yourScrollView as argument. Hope this will help you.........
According to Apple... When debugging issues with text views, watch for this common pitfall:
Placing a text view inside of a scroll view. Text views handle their own scrolling. You should not embed text view objects in scroll views. If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled.
I'm trying to use a UIWebView for displaying content higher than the screen of the iPhone, without needing to scroll in the UIWebView itself.
The UIWebView is placed as a subview to a UIScrollView, along with some other objects that I want the UIScrollView to scroll up and down with the UIWebView.
I know you can do this with a UITextView like this:
CGRect frame = _textView.frame; frame.size.height = _textView.contentSize.height; _textView.frame = frame;
But the UIWebView does not inherit from UIScrollView and does therefore not contain the contentSize-property.
I'd really like to keep it a UIWebView, because the data I get is in HTML-blocks.
Thank you!
In fact, no Javascript is needed!
In UIView there is a nice method:
- (CGSize)sizeThatFits:(CGSize)size
You pass it anything (not really meaningful here), and it returns the size it'd like to be, using its content (subviews, etc) to compute the size.
Of course, since content loading in a UIWebView in asynchronous, you should do this after the webview has loaded, for instance in the UIWebViewDelegate method:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
CGSize size = [webView sizeThatFits: CGSizeMake(1.0f, 1.0f)]; // Pass about any size
CGRect frame = webView.frame;
frame.size.height = size.height;
webView.frame = frame;
}
Et voila!
I think the only way you'll be able to do this is to use some javascript to get the size of the web page and adjust the size of the UIWebView control.
Something like the following should do the trick
int content_height = [[theWebView stringByEvaluatingJavaScriptFromString: #"document.body.offsetHeight"] integerValue];
CGRect rect = theWebView.frame;
rect.size.height = content_height;
theWebView.frame = rect;
You may need to add some sort of fudge factor to the content height.