I am designing an app which will present large amounts of text that is interspersed with notes and references as clickable images. On a PC I'd use a control that shows HTML, but in the iPhone I am not able to intercept the touches of images and links too well using the UIWeb control.
Should I use a UIScroll and build the text as lables and UIImages perhaps?
Looking for the best way forward in my design phase.
I don't know what your requirements are obviously, but it is possible to capture the click on an link in a UIWebView and take some alternative action. In one of my Apps, I have a UIWebView with one particular link which I want to route differently, while I let all other links open as web pages in the UIWebView as normal. Here's the code snippet from the app which accomplishes this. It is within a UIViewController which loads the UIWebView:
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [ request URL ];
if( [[url path] isEqualToString:#"/the_special_link.html"] ) {
// Take some alternative action and then stop the page from loading...
// (code to take some special action goes here)
return NO;
}
else {
return YES;
}
}
This is a delegate method call, so when I set up the UIWebView, which I do programmatically in the Controller loadView method, I set the WebView's delegate to that same Controller:
myWebView.delegate = self;
Related
I am trying to build a simple app that uploads images to my site. I am using this tutorial:
http://www.youtube.com/watch?v=aQXaJO36I7Y
What I want to do instead of using a button from the app's interface I wan to use a button within a website in a webview. So I want a button to call the opening of the photo album to select a image to upload.
Basically I need a way for a javascript function to call a action in the app itself.
How can I do this?
You could just use a custom link, which you can then detect in the UIWebViewDelegate method.
- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSString *rawURL = [[request URL] absoluteString];
if([rawURL isEqualToString:#"callImageLib://"]) {
[self methodeForImageLib];
}
return NO;
}
return YES;
}
If i understand it correctly you need to communicate iPHone Web application to call native iPhone application and visa versa. please check the following links.
http://blog.techno-barje.fr/post/2010/10/06/UIWebView-secrets-part3-How-to-properly-call-ObjectiveC-from-Javascript
http://iphoneincubator.com/blog/windows-views/how-to-inject-javascript-functions-into-a-uiwebview
hope these 2 link help to solve your issue.
My app features content that (for text formatting reasons) is presented in an UIWebView. Within the content there are links, some of which should open their target in mobile Safari, while others should navigate within the content.
So far, I've catched the link requests using a UIWebView delegate. In my implementation of
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
I'd check the requests URL using lastPathComponent or pathComponents for known elements to determine whether to open the link externally or within the view.
However, I just found out said methods are only available since iOS 4.0, which would render the app useless on iPad. Plus I have the feeling I'm using a dirty solution here.
Is there another way to somehow "mark" the links within my content in a way that makes them easy to distinguish later, when processing the request in the delegate method?
Thanks alot!!
You could covert the URL request into a string, and do a compare for a subdirectory on your website, such as in URLs that only start with "http://www.sample.com/myapp/myappswebcontent/", against the initial substring of your URL. Anything else, send to Safari.
You should set a policy delegate of web view:
For instance in the controller, that contains a web view
[webView setPolicyDelegate:self];
and then override a decidePolicyForNavigation method (this is just an example):
- (void)webView:(WebView *)sender decidePolicyForNavigationAction: (NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id <WebPolicyDecisionListener>)listener
{
if ([[actionInformation objectForKey:WebActionNavigationTypeKey] intValue] == WebNavigationTypeLinkClicked) {
[listener ignore];
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
}
else
[listener use];
}
you can distinguish there kind of link and ignore or use the listener. If you ignore it, you can open the link in safari, if you use it, the link will open in your webview.
HTH
I've designed my main view using HTML, CSS and some images. It looks very nice. I'm using some images that are clickable in HTML code.
On click of some image, I want to load some view accordingly.
Is it possible? If yes, please suggest me how to do it.
If tutorial or some sample code is available please share it.
Implement the following UIWebView Delegate Method and call your Objective methods
(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSLog(#"LINK CLICKED......");
//return NO;
}
return YES;
}
You can look into PhoneGap for some sample code.
There are two parts. First you define a custom scheme for you application that is only used to communicate between the web page and the delegate. Could just be 'foo:' as it will be private to the page and host. You then handle this custom scheme in the delegate shouldStartLoadWithRequest method and return NO.
With a clickable link, you can just set the href to something that starts with your custom scheme. If you need to send messages at arbitrary times, you can use javascript to set the window.location to a url with your custom scheme.
I wanna wrap some text around a UIButton or clickable image in some kind of scrollview.
My ide was to add an UIButton to an UIWebView, but thats not possible?
Is there a way to wrap text around an UIButton in an UIScrollView or UITextView?
Or can I add an image to the UIWebView and handle the clicking somehow?
In the current SDK there is no easy way to wrap text around an image. You could make multiple UILabels and manually cut the strings up into pieces, but that is difficult in itself.
If you make the image a normal anchor, you can handle the opening of the link in the UIWebView delegate callbacks. Return NO and do whatever you want the image to do. You can use a custom scheme to make it easy to distinguish.
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( [[[inRequest URL] scheme] isEqualToString:#"myscheme"] ) {
// do something
return NO;
}
return YES; // normal link
}
In a UIWebView, you have nearly full access to css and javascript and can do almost anything you could do in Safari. You are not limited to using an anchor tag, that is just the easiest way.
I have a UIWebView and a UITextField for the url. Naturally, I want the textField to always show the current document url. This works fine for urls directly input in the field, but I also have some buttons attached to the view for reload, back, and forward.
So I've added all the UIWebViewDelegate methods to my controller, so it can listen to whenever the webView navigates and change the url in the textField as needed.
Here's how I'm using the shouldStartLoadWithRequest: method:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"navigated via %d", navigationType);
//loads the user cares about
if ( navigationType == UIWebViewNavigationTypeLinkClicked
|| navigationType == UIWebViewNavigationTypeBackForward ) {
//URL setting
[self setUrlQuietly:request.URL];
}
return YES;
}
Now, my problem here is that an actual click will generate a single navigation of type "LinkClicked" followed by a dozen type "Other" (redirects and ad loads I assume), which gets handled correctly by the code, but a back/forward action will generate all its requests as back/forward requests.
In other words, a click calls setUrlQuietly: once, but a back/forward calls it multiple times.
I am trying to use this method to determine if the user actually initiated the action (and I'd like to catch page redirects too). But if the method has no way of distinguishing between an actual "back" and a "load initiated as a result of a back", how can I make this assessment?
Without this, I am completely stumped as to how I can only show the actual url and not intermediate urls. Thank you!
Ok here's what I ended up doing - not sure if this is the expected solution though. Scratch all the code from the above method and instead do this:
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSString *urlString = [self.webView stringByEvaluatingJavaScriptFromString:#"document.URL"]
[self setUrlQuietly:[NSURL URLWithString:urlString]];
}
This means there's a slight delay between clicking a link etc and seeing the url show up in the textField, but it also guarantees that the textField always shows the document's actual title.
I'm not seeing the UIWebViewNavigationTypeBackForward event at all. And sometimes webViewDidStartLoad never gets called. Perhaps there have been some changes in iOS 5.
Anyway, here's my solution for keeping the title and URL up to date. Works very consistently, though the response could be a little faster.
- (void)webViewDidFinishLoad:(UIWebView *)wv
{
[self updateButtons];
titleLabel.text = [wv stringByEvaluatingJavaScriptFromString:#"document.title"];
NSURL *url = wv.request.URL;
[selectedUrl release];
selectedUrl = [url retain];
}