Programmatically focus on a form in a webview (WKWebView)
After digging into the Webkit sources for a couple of weeks, I've managed to get this working on iOS 9 by swizzling _startAssistingNode:userIsInteracting:blurPreviousNode:userObject
on WKContentView
and overriding the userIsInteracting value:
Pseudo code:
swizzle_intercept("WKContentView", "_startAssistingNode:userIsInteracting:blurPreviousNode:userObject:", &hackAssist);
void hackAssist (id self, SEL _cmd, void* arg0, BOOL arg1, BOOL arg2, id arg3) {
((void (*)(id,SEL,void*,BOOL,BOOL,id))swizzle_interceptee(hackAssist))(self, _cmd, arg0, TRUE, arg2, arg3);
}
Cheers!
How can I get a UIWebView to focus on a form input and bring up the keyboard?
This is now possible with iOS 6.
UIWebView* webView = <#your webView here#>;
[webView setKeyboardDisplayRequiresUserAction:NO];
[webView loadHTMLString:@"<html><head></head><body><form><input id=\"textField\" /></form><script>document.getElementById(\"textField\").focus();</script></body></html>"
baseURL:nil];
WKWebView migration issues
I have now managed to get the keyboard displayed by adding
[self allowDisplayingKeyboardWithoutUserAction];
to viewDidLoad
I kept the allowDisplayingKeyboardWithoutUserAction method declaration inside my ViewController but changed the + infront of the method declaration to a - and this seems to have worked.
I still do not know how to resize the webview when the keyboard is displayed.
Accessing DOM element in WKwebView
You're reading the wrong class' docs. WebView and WKWebView are not the same. The latter is faster and more secure but not as manipulable.
For WKWebView, you'd want to use wkwebview.evaluateJavaScript to send a whole string of code that does the manipulations to the DOM. The completionHandler can asynchronously receive simple results like strings and numbers and fire off more JS evaluations based on those, but you can't receive DOM element references and directly tweak their properties from Swift.
accessibility on WKWebView on first launch
Try using becomeFirstResponder()
-
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let myWebView:WKWebView = WKWebView(frame: CGRect(x:0, y:0, width: UIScreen.main.bounds.width, height:UIScreen.main.bounds.height))
myWebView.uiDelegate = self
self.view.addSubview(myWebView)
//1. Load web site into my web view
let myURL = URL(string: "https://www.apple.com")
let myURLRequest:URLRequest = URLRequest(url: myURL!)
myWebView.load(myURLRequest)
myWebView.becomeFirstResponder()
}
UIWebView scrolling down on input focus iOS 6 only
Without knowing the inner workings of your code, I'm going to try to help as much as I can. If nothing else, I hope to provide some food for thought. You asked two questions:
Is it expected behavior in iOS6?
What you're seeing is quite odd for sure. It's strange that the webView is centering the form rather than centering the input field. And it should definitely not cause the active input field to scroll out of view. Furthermore, the keyboard seems to stop working, which is quite odd. However, it is expected to see different behavior in iOS 5 and 6 with regards to the webView scrolling. As you said, iOS 5 scrolls the inputField into view while iOS6 puts it in center.
Is there any way to keep the webview from scrolling when an input gains focus (like how iOS 5 works)?
Yes. I provide code to do just this below -- namely to stop the webView from scrolling. If that is exactly what you want to do, then great. However, stopping the webView from scrolling is not the same as getting the same behavior as iOS5. Still, I wanted to give you this option as you requested it.
#import "ViewController.h"
@interface ViewController () <UIScrollViewDelegate> {
CGPoint origin;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.google.com"]];
[self.webView loadRequest:request];
self.webView.scrollView.delegate = self;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow)
name:UIKeyboardWillShowNotification
object:nil];
// NOTE THAT SIMPLY DISABLING THE SCROLL WILL NOT PREVENT KEYBOARD SCROLL
//[self.webView.scrollView setScrollEnabled:NO];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)keyboardWillShow {
NSLog(@"keyboard");
origin = self.webView.scrollView.contentOffset;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(@"scroll");
[self.webView.scrollView setContentOffset:origin];
}
@end
If you want consistent scroll behavior...
I took some time to code up this scroll modification. You can use it as a reference in making your own scroll behavior that is consistent across iOS 5&6. In this code: When the user clicks on a text input box on a webpage, the code will stop the default scrolling behavior by keeping the page scrolled to its current position. Unfortunately, there is no way to cancel all scrolling, but rather you have to override scrolls. Once the default scrolling has been "suppressed", it gets the position of the active input box and scrolls to that position. This will put the active input box in the top of the screen. You can modify this according to your preferences. For example, you can use [UIScrollView scrollRectToVisible] to make it more like iOS5.
#import "ViewController.h"
@interface ViewController () <UIScrollViewDelegate> {
CGPoint origin;
CGPoint activeElementOrigin;
BOOL pauseScroll;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.google.com"]];
[self.webView loadRequest:request];
self.webView.scrollView.delegate = self;
pauseScroll = NO;
origin = CGPointZero;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidShow)
name:UIKeyboardDidShowNotification
object:nil];
}
- (void)keyboardWillShow {
NSLog(@"keyboard");
pauseScroll = YES;
origin = self.webView.scrollView.contentOffset;
}
- (void)keyboardDidShow {
NSLog(@"keyboard DID SHOW");
pauseScroll = NO;
[self.webView.scrollView setContentOffset:activeElementOrigin animated:YES];
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(@"scroll");
if (pauseScroll) {
[self.webView.scrollView setContentOffset:origin animated:NO];
NSString *javaScript = [NSString stringWithFormat:@"function f(){ var textField = document.activeElement; return textField.getBoundingClientRect().top; } f();"];
NSString *textFieldRectTop = [self.webView stringByEvaluatingJavaScriptFromString:javaScript];
activeElementOrigin = origin;
activeElementOrigin.y = [textFieldRectTop floatValue]-10;
}
}
@end
If this code helped you, it would be very nice of you to reward the bounty to me.
I would be humbly appreciative.
Related Topics
Uiview Atop the Keyboard Similar to Imessage App
Ios7 Safari: Saving to Home-Screen and Persist Token
Reading Long Characteristic Values Using Corebluetooth
Editing Screenshots in Itunes Connect After iOS App Was Approved
How to Calculate the Height of an Nsattributedstring with Given Width in iOS 6
Change the Font Size of Uisearchbar
How to Define the Size of a Collectionview on Rotate
Does Firebase Cloud Messaging Support Voip Pushkit Services
Objc_Sync_Enter/Objc_Sync_Exit Not Working with Dispatch_Queue_Priority_Low
Show Uipickerview Text Field Is Selected, Then Hide After Selected
Uiwebview Random Crash at [Uiviewanimationstate Release]: Message Sent to Deallocated Instance
How to Use Avsamplebufferdisplaylayer in iOS 8 for Rtp H264 Streams with Gstreamer
Swiftui - Detect When Scrollview Has Finished Scrolling
How to Use Icloud to Sync the Nsuserdefaults Plist File
Detect When a Webview Video Becomes Fullscreen on iOS8
How to Hide First Section Header in Uitableview (Grouped Style)