I'm creating ipad application. It has just 2 views.
One view has few buttons. On click of a button it will open another view. This view has a webview which shows PDF file. I'm using the following code to show the PDF
- (void)viewDidLoad {
[super viewDidLoad];
NSString* path = [[NSBundle mainBundle] pathForResource:#"mypdf" ofType:#"pdf"];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]];
}
Now the problem is that, when I change the orientation, whole view is rotating, but the pdf is being disturbed and not rendering properly. how can I avoid this?
As the PDF is having 250 pages, reloading the whole PDF on willRotateToInterfaceOrientation and didRotateFromInterfaceOrientation will delay the display.
How to avoid this situation.
There has to be a way a better to avoid/fix this, for now i just read the y scroll position with:
int scrollPosition = [[webView stringByEvaluatingJavaScriptFromString:#"window.pageYOffset"] intValue];
Then reloaded the document in:
(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;
and then set the scroll position again with:
[webView stringByEvaluatingJavaScriptFromString: [NSString stringWithFormat:#"scrollTo(0,%d)",scrollPosition];
Related
One of my apps has a UIWebView which loads a particular pdf from the user's device. After the webView has loaded I would like to set the zoom scale and contentOffset. However, if the pdf takes a while to load, the user can no longer scroll - they can see the whole pdf and can zoom in/out, but it only zooms into the top-left corner and you can't scroll at all. (You can scroll if you zoom in further than zoom scale).
(For completeness) I run this code in viewDidAppear:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *path = [documentsPath stringByAppendingPathComponent:#"filename.pdf"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
The main code:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if (!loadFailedBool) {
[self performSelector:#selector(zoomIntoWebView) withObject:nil afterDelay:0.0];
}
}
- (void)zoomIntoWebView {
[webView.scrollView setZoomScale:5.0 animated:NO];
webView.scrollView .contentOffset = CGPointMake(600, 420);
}
I have removed any unnecessary code, but as you can see, it runs the zoom function after a delay of 0.0. In this circumstance, the above bug happens every time. If I set it to something like 0.3 the code works fine, about 90% of the time.
As a temporary fix, I have set the delay to 0.6 but it is far from ideal, especially if a user is on a older device. If this bug happens every time, this feature of the app becomes unusable. If anyone has any suggestions or a similar problem it will be great to find a solution. Knowing when the pdf has finished loading would probably fix it.
I am trying to display a pdf in a UIWebview using the entire screen of the device, except the status bar and top bar. So far, I created IBOutlet UIWebview *webview; in my .h file. I connected the webview in my storyboard and wrote the following code in my .m file:
- (void)viewDidLoad
{
[super viewDidLoad];
webview = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
webview.scalesPageToFit = YES;
webview.autoresizesSubviews = YES;
webview.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[webview setBackgroundColor:[UIColor clearColor]];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Chart" ofType:#"pdf"];
NSURL *targetURL = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:targetURL];
[webview loadRequest:request];
[self.view addSubview:webview];
}
The pdf displays correctly in my 3.5 inch, but in my 4 inch display, the bottom is cut off. This is even more noticeable when I rotate to landscape view. About 33% of the screen is not used at all. How can I fix this? I know it must have something to do with the UIWebview dimensions in my code above (webview = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];), but is there a better way to simply display the webview on the entire screen, without specifying a specific screen height and width?
One cheap thing to do would be to set the frame of the webview in overriding - (void)viewDidLayoutSubviews
- (void)viewDidLayoutSubviews {
webView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
the advantage of doing it here, is that the size and orientation of the view has already been determined here, and you can get an accurate measurement.
Using Auto Layout
Be sure the "Constrain to margins" option is not checked, all constrain values are 0:
And your webview is a first child of your main view:
Without Auto Layout
Change webview autosizing connections:
After a lot of headache dealing with compatibility of iOS6, 7 and different screen sizes, I use this one:
- (void)viewDidLoad {
[super viewDidLoad];
self.webview = [[UIWebView alloc] init];
// More setting your webview here
// Set webview to full screen
self.view = self.webview;
[self.webview loadRequest:aRequest];
}
I was able to get this working correctly for me by selecting the Reset to Suggested Constraints under the Resolve Auto Layout Issues menu.
I tried every permutation known to mankind and I cannot get a UIWebView to size properly in a modal form view for the iPad. The web page still displays the full iPad portrait width of 768 points.
Where and how do I tell UIWebView to display width 540 points?
I thought 'scalesPageToFit' is supposed to do this but it does not work.
I tried setting the web view to the size of form view which is 540 x 576 with navigation and status bar. Height is irrelevant though.
I tried adding a UIWebView to a UIView in a storyboard with all resizing set. I then removed the UIWebView and added it programmatically.
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect aFrame = self.view.frame;
if (IS_IPAD)
{
aFrame = CGRectMake(0, 0, FORM_VIEW_WIDTH, FORM_VIEW_HEIGHT);
}
_webView = [[UIWebView alloc] initWithFrame:aFrame];
[_webView setOpaque:NO];
[_webView setDelegate:self];
[_webView setScalesPageToFit:YES];
self.view = _webView;
...
}
I also tried loading in viewDidAppear (in addition to viewDidLoad, viewWillAppear, etc.)
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[self webView] setFrame:CGRectMake(0, 0, FORM_VIEW_WIDTH, FORM_VIEW_HEIGHT)];
[[self webView] setScalesPageToFit:YES];
NSURL *webURL = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:webURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0f];
[[self webView] loadRequest:request];
}
Any recommendations appreciated.
This keeps happening to me. I post a lengthy question, then two seconds later I find the answer.
Anyway, someone posted a solution to this problem here:
UIWebView -- load external website, programmatically set initial zoom scale, and allow user to zoom afterwards
However, I altered the script to set the width to the iPad width:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString* js =
#"var meta = document.createElement('meta'); "
#"meta.setAttribute( 'name', 'viewport' ); "
#"meta.setAttribute( 'content', 'width = 540px, initial-scale = 1.0, user-scalable = yes' ); "
#"document.getElementsByTagName('head')[0].appendChild(meta)";
[[self webView] stringByEvaluatingJavaScriptFromString: js];
}
Note the portion 'width = 540px, initial-scale = 1.0, user-scalable = yes'
I changed the width to the form width and scale to 1.0.
I also need to handle iPhone, and so I will make adjustments for that next. I think this fix may only be needed for the iPad form view.
UPDATE: Answer is short-lived. If I load any other page the sizing is thrown off again. Back to square one.
SOLUTION: This view will only need to access a few web pages that I developed. Therefore, I updated the few web pages that I need to access by adding the meta tag to each of them. I only need to access these pages and so this is the solution I plan to go with. This means I need to set the viewport width to 540px only for iPad somehow. I will figure that out next.
<meta name="viewport" content="width:540, initial-scale=1, maximum-scale=1">
I've one ppt file locally that I'm opening with UIWebView with below code, file having 10 slides, now with the requirement, I want to jump to a specific slide, something like if I want to directly jump to slide#3 then how to do it with this code?
-(void)loadDocument:(NSString*)documentName inView:(UIWebView*)webView
{
NSString *path = [[NSBundle mainBundle] pathForResource:documentName ofType:#"ppt"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
}
//open ppt into UIWebView like,
[self loadDocument:#"newone" inView:self.myWebview];
I searched here, and found this, they are doing
Link to http://www.whatever.com/hello.ppt#4 for slide 4 to be opened initially.
but my ppt file is saved into document directory (locally) within my app.
Any suggestion?
You can set the offset of UIWebview ScrollView.
[[webView scrollView] setContentOffset:CGPointMake(widht, height) animated:YES];
Find height of one slide in current zoom scale. Multiply it with four as forth page to open initially. and put in above code with point CGPointMake(0, heightYouCalculated)
I have a set of local HTML pages that I would like batch generate thumbnails for on the fly (I only want to show the thumbnails, not the full web pages). This is the way I'm accomplishing this:
NSString* path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:link];
NSURL* url = [NSURL fileURLWithPath:path];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
UIWebView* webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 725, 1004)];
webView.delegate = cell;
[webView loadRequest:request];
[self.view addSubview:webView]; // doesn't work without this line, but then the UIWebView is onscreen
Then in the delegate:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[self performSelector: #selector(render:) withObject: webView afterDelay: 0.01f];
}
- (void) render: (id) obj
{
UIWebView* webView = (UIWebView*) obj;
CGSize thumbsize = CGSizeMake(96,72);
UIGraphicsBeginImageContext(thumbsize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat scalingFactor = thumbsize.width/webView.frame.size.width;
CGContextScaleCTM(context, scalingFactor,scalingFactor);
[webView.layer renderInContext: context];
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.thumbnail.image = resultImage;
}
Here are my questions:
1) Is my general approach correct? Is this the most efficient way to batch process thumbnails of webpages on the fly?
2) I want to be able to render the thumbnail from an offscreen UIWebView, but the webViewDidFinishLoad: doesn't get called unless I add the UIWebView to the view hierarchy. Is there a way I can avoid this?
3) If I attempt to capture an image of the UIWebView in webViewDidFinishLoad:, I get a blank image. I have to put an artificial delay for the capture to work. Any way around this?
Thanks!
1) This seems to be the only way I know of to do this, without relying on a third party server-based API (if one exists)
2) You can draw the UIWebView off-screen by setting its frame to a position that is off-screen. For example 320,568,725,1008. I haven't tested it, but you should even be able to set the view as a 1 x 1px frame.
3) I imagine this is because when webViewDidFinishLoad: is called, a SetNeedsDisplay() has been called on the web view, but the web view has not yet redrawn itself. I'm not sure about a way around this.