UIWebView's scrolling after textfield focus - ios

I have UIView and UIWebView on screen. When I click on text field in website, web view content is going up. How could I force UIView to move as well then?

You can subscribe to either the UIKeyboardWillShowNotification or the UIKeyboardDidShowNotification, and move your UIView when you receive the notification. This process is described here:
Text, Web, and Editing Programming Guide for iOS: “Moving Content That Is Located Under the Keyboard”

Maybe this helps: I didn't want the UIWebView to scroll at all, including when focusing on a textfield.
You have to be the delegate of the UIWebView:
_webView.scrollView.delegate = self;
And then add this method
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
scrollView.contentOffset = CGPointZero;
}

UIWebView has a callback:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
This is triggered whenever a new URL request is about to load. From javascript, you could trigger a new request URL on the onfocus event of the tag, with a custom schema like:
window.location = "webViewCallback://somefunction";
Here's a script to put your custom event inside any html page to load.
You'll have to get the whole HTML before loading it to the UIWebView like this:
NSString *html = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"your URL"] encoding:NSUTF8StringEncoding error:nil];
Then insert the following inside the HTML text in a appropriate place:
<script>
var inputs = document.getElementsByTagName('input');
for(int i = 0; i < inputs.length; i++)
{
if(inputs[i].type = "text")
{
inputs[i].onfocus += "javascript:triggerCallback()";
}
}
function triggerCallback()
{
window.location = "webViewCallback://somefunction";
}
</script>
Then, on the callback you should do something like this:
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( [[inRequest URL] scheme] == #"webViewCallback" ) {
//Change the views position
return NO;
}
return YES;
}
That's it. Hope it helps.

Wow, I had the same problem few days ago, it was really annoying. I figured out that window.yPageOffset is changing, but as far as I know there aren't any events to bind when it changes. But maybe it will help you somehow. ;-)

I think you overwrote scrollViewDidScroll wrong.
You need to implement custom class for UIWevView and overwrite scrollViewDidScroll:
- (void) scrollViewDidScroll:(UIScrollView *)scrollView{
[super scrollViewDidScroll:scrollView];
[((id<UIScrollViewDelegate>)self.delegate) scrollViewDidScroll:scrollView];
}

Related

How to call a method when a URL is hit inside UIWebView?

I am loading a URL inside UIWebView. It opens a web-page which contains some URL links. Is it possible that I call a method when particular link is clicked.
I simply want to detect the URL clicks inside UIWebView in my iOS App.
Thanks.
Yes, there is method in UIWebViewDelegate protocol. Add your controller as delegate to UIWebView.
self.webView.delegate = self;
Then implement delegate's method:
- webView:shouldStartLoadWithRequest:navigationType:`
You should read it's documentation. As you can see, one parameter is navigationType, you interested only in UIWebViewNavigationTypeLinkClicked.
Like Timur says add into your viewController the UIWebViewDelegate
Then you can use the method like this:
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( [[[inRequest URL] scheme] isEqualToString:#"js-call"] ) {
// Do something interesting...
return NO;
}
return YES;
}
Then i've used a js call, but you can use also links:
window.location.href = "js-call:myEvent";

How can I prevent the webView from being visible till webViewDidFinishLoad is finished?

I'm removing content of the webView in the webViewDidFinishLoad. The problem is it first loads the page and shows all the content and then you will see the content I'm removing disappear. I would like it so that the user doesn't see anything disappear so the content should never been shown to the user.
This is my method :
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString* script = [NSString stringWithFormat:#"document.getElementById('menu').style.display='none';"];
[self.webView stringByEvaluatingJavaScriptFromString:script];
NSLog(#"gets");
}
The trick is use of isLoading property.
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
if(!webView.isLoading){
//Has completely stopped..
}
}
Use webview.hidden = YES till the time you dont want to see the data and then set it as no again
You can use the UIWebView Delegate methods as shown below.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
webView.hidden = YES;
return YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
webView.hidden = NO;
}
Isn't the same thing work in viewDidLoad ?
-(void)viewDidLoad{
NSString* script = [NSString stringWithFormat:#"document.getElementById('menu').style.display='none';"];
[self.webView stringByEvaluatingJavaScriptFromString:script];
NSLog(#"gets");
}

iOS - how to let a view both respond a touch and let it pass through it

I'd like to have my UIWebView respond to touch event from user, and also let views from behind respond to touch. Is it possible?
basically, i'd like to have my UIWebView interact with a touch but not "swallowing" it, and let it go through for another lower view too.
The short answer, I believe, is no.
The best that you could do is to capture the touches in the UIWebView using one or more UIGestureRecognizers and then manually manipulate or trigger actions in the lower UIViews.
This is possible if an only if your webview is made by you. It will be done in PHP code for that site ie. when you tap on any button or any event is detected on your webview, then a parameter can be passed by PHP code from server in form of hidden field. You can recieve this by following code:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//NSString *html = [webView stringByEvaluatingJavaScriptFromString:#"document.body.innerHTML"];
//NSLog(#"%#",html);
NSString *hdnPaymentStatusId = [webView stringByEvaluatingJavaScriptFromString: #"document.getElementById('yourParametrer1').value"];
NSLog(#"value%#",hdnPaymentStatusId);
if ([hdnPaymentStatusId integerValue] == 1)
{
DWMyOrdersViewController *myOrderVC = [self.storyboard instantiateViewControllerWithIdentifier:#"DWMyOrdersViewController"];
[self.navigationController pushViewController:myOrderVC animated:YES];
}
NSString *hdnCancelStatusId = [webView stringByEvaluatingJavaScriptFromString: #"document.getElementById('yourParametrer2').value"];
NSLog(#"value%#",hdnCancelStatusId);
if ([hdnCancelStatusId integerValue] == 1)
{
[self dismissViewControllerAnimated:YES completion:nil];
}
}

Duplicate Method Issue

I'm very new to Objective-C and the syntax and everything. I wrote two separate methods, but ran into the error: Duplicate declaration of method webView:shouldStartLoadWithRequest:navigationType:
So, it looks like I need to combine both of my webView:shouldStartLoadWithRequest:navigationType: methods. The only issue is, they both contain if statements and return values, and that super confused me. These are the two methods:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *full = [request.URL absoluteString];
if ([full isEqualToString:#"ExampleURL.com"] || [full isEqualToString:#"ExampleURL.com"]
|| [full isEqualToString:#"ExampleURL.com"] ) {
return YES;
}
else
return NO;
}
And:
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *full = [request.URL absoluteString];
if ([full isEqualToString:#"ExampleURL.com"]) {
_backButton.hidden = YES;
return NO;
} else {
_backButton.hidden = NO;
}
return YES;
}
I've been trying to combine these two methods into one for a long time now, and am at a loss. It's the if statements that are tripping me up. Does anyone know how I could do this or what it would look like?
Side note: My desired goal is to only allow specific URLs to load. At the same time, I need the back button to be hidden only when one website is loaded. Does anyone know if there would be a way to hide / show the back button based on a URL by avoiding this method all together? I think I may be going about this wrong.
What's your desired logic here? One method will be called when the WebView starts loading. You will do some stuff, then return YES or NO based on whether you want the loading to proceed. You can't tell it it's ok to load and then tell it that it's not ok to load at the same time.
In your two methods you have this:
if ([full isEqualToString:#"ExampleURL.com"] || ...snipped... ) {
return YES;
}
And then this
if ([full isEqualToString:#"ExampleURL.com"]) {
// ...
return NO;
}
Which check the same thing but then return opposite values.
So I'll answer generally. This is sort of the general form of this method.
-(BOOL) webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
// alter application state
// return YES or NO
}
Lets say you want to do this, which I'm not sure is what you want, but this is the general idea:
if loading ExampleURL.com, then show the back button and allow the load
otherwise, hide the button and do not allow the load.
Then you might implement this method like so:
-(BOOL) webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
if ([[request.URL host] isEqualToString:#"ExampleURL.com"]) {
_backButton.hidden = NO;
return YES;
} else {
_backButton.hidden = YES;
return NO;
}
}
Now adjust that to reflect the logic you actually want.
I think you are trying to do something like this:
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
NSString *full = [request.URL absoluteString];
if([full isEqualToString:#"hidebackbuttonforthiswebsite.com"])
_backButton.hidden = YES;
if ([full isEqualToString:#"AcceptedURL1.com"] ||
[full isEqualToString:#"AcceptedURL2.com"] ||
[full isEqualToString:#"AcceptedURL3.com"])
{
// Good URL, load it
return YES;
}
else
{
// Bad URL, so don't load it
return NO;
}
}
This will hide the back button for the specific URL, and then allow only a specific set of URLS to load. It sounded like this is what you want, but it's hard to understand your explanation.
I general, you might consider an additional conditional inside the method to determine what condition tree to use.
That could be another method called within this one.
You might also consider adding an additional argument to the method parameters if you need some criterion to determine conditional logic inside the method.
Another option, if you have two methods that cannot be merged because they do different things, but they have the same argument list, you should change the selectors (method signature) to distinguish them and make sure the selector indicates what they do differently.

Creating Terms and Conditions link

"By clicking Register you are agreeing to our Terms and Conditions"
What is the easiest option to implement in the code where the entire above line is made clickable (this launches a modal view that shows the terms and conditions) AND the word "terms and conditions" is underlined in blue.
We tried various options.
1) We created a UIWebView and tried loading a html into it. But the html was rendered as is.
eg: "html body.../body html"
2) We tried to create a button with a label over it but we were not able to create a borderless button.
Thanks!
We were able to create the formatting by using a webView. We used one of the delegate of webView to complete the process. Here is sample code
NSString *html = #"<html><head><title>Terms and Conditions</title></head><body style=\"font-family:verdana;font-size:10px;\"><p>By clicking \"Register\" you are agreeing to our <b><u><font color=\"blue\">Terms and Conditions.</font></u></b></p></body></html>";
[termsWOutlet loadHTMLString:html baseURL:[NSURL URLWithString:#"http://www.google.com/message"]];
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"%s",__FUNCTION__);
NSURL* u = [request URL];
if( [[u scheme] isEqualToString:#"showlicenses"] ) {
NSLog(#"in %s",__FUNCTION__);
[self performSegueWithIdentifier:#"loadTNC" sender:self];
return NO; // DO NOT attempt to load URL
}
return YES; // if you want to allow the URL to load
}

Resources