Before iOS16,I can use UIRemoteKeyboardWindow window to get the system keyboard and then access the send button to click it. But after the system was updated to iOS16, UIRemoteKeyboardWindow is deprecated. Is there any other way to get the keyboard window? Or is there a way to directly trigger the keyboard send event?
I tried to use the UITextEffectsWindow, but it can't access the elements of the keyboard.
I tried to access the UIInputSetHostView view in UITextEffectsWindow, which is the window where the keyboard is located. and I estimate the position of the send button, finally tap on this location with tapAtPoint, but it doesn't seem to work.
Here is my code
if(#available(iOS 16, *)){
NSString *elementClass = NSStringFromClass(element.class);
if([elementClass isEqualToString:#"UIInputSetHostView"] && [infoItem.requestLabelName isEqualToString:#"Send"]){
CGSize sendPoint = tmpItem.view.frame.size;
CGPoint originPoint = tmpItem.view.frame.origin;
point.x = sendPoint.width * 0.85;
point.y = sendPoint.height * 0.8;
}
[view tapAtPoint:point];
}
Related
I followed the instructions here to adjust my view with the iOS keyboard.
https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
This doesn't work with a hardware keyboard. When a text view is active the iOS keyboard is not shown but the example code still returns the full height of the keyboard. In my case just the input accessory view is shown on the screen.
How do I detect this case and adjust my view for only the input accessory view?
You can intersect the keyboard's frame with the current window as in my answer here https://stackoverflow.com/a/36553555/1049134.
Came across the same issue.
Looks like the iOS keyboard is completely instantiated and just moved out of the view partial when a hardware keyboard is attached. Therefore the size of the keyboard is right. It is just not completely shown.
After examining the notifications I solved it with calculating the visible keyboard height myself.
In my example I am listening to UIKeyboardWillShowNotification, UIKeyboardWillChangeFrameNotification and UIKeyboardWillHideNotification.
-(void)keyboardMessage:(NSNotification*)notification {
NSDictionary *userInfo = notification.userInfo;
CGFloat duration = [userInfo[#"UIKeyboardAnimationDurationUserInfoKey"] floatValue];
NSValue *value = userInfo[#"UIKeyboardFrameEndUserInfoKey"];
CGRect frame = [value CGRectValue];
[UIView animateWithDuration:duration animations:^{
self.lowerContraint.constant = self.view.frame.size.height - frame.origin.y;;
[self.view needsUpdateConstraints];
[self.view layoutIfNeeded];
}];
}
Is it possible to receive a local notification when Predictive is enable/disabled.
I have a UITextView and when Predictive is enabled, the inputAccessoryView of this textView moves up and it hides the last line in textView. If its possible to get notification that Predictive has changed, I can resize the textView.
I searched but could not find any way to receive the notification.
I also did not find any delegate methods for this in UITextViewDelegate.
Any help would be highly appreciated.
Why not move up little bit your view when you start typing and solved this issue :)?
Use UITextFieldDelegate and use this code (you can animate this if you want)
- (void)textFieldDidBeginEditing:(UITextField *)textField{
CGRect rect = self.view.frame;
rect.origin.y = - 30; //enter pixels number to pushup your view
self.view.frame = rect;
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
CGRect rect = self.view.frame;
rect.origin.y = 0; //return to 0.0 position.
self.view.frame = rect;
}
Have you tried to listen to the notifications received from UIKeyboardWillShowNotification and UIKeyboardWillHideNotification?
Here's my setup: I want to programmatically...
Raise the built-in keyboard (by giving focus to a text field)
Programmatically animate a finger graphic moving over the keyboard.
Fake a tap on the keyboard and have the keyboard respond to that tap.
The use-case is to create a video showing "look, you can type, and this is what happens...", but with a stylized and partially transparent finger-image, rather than somebody's actual finger blocking the view.
Related: I can map the X/Y coordinates for my video easily enough, but bonus points if anyone can help me get the position of a given key on the keyboard, thus simplifying my writing of the routine fakeTypeText: #"Hello World!" to move the point of the finger to the correct location.
Thanks!
EDIT: Use case sample code...
- (void) fakeTypeText: (NSString*) text
{
int len = (int) text.length;
for (int ii = 0 ; ii < len ; ++ii)
{
char oneChar = [text characterAtIndex: ii];
// *** BONUS POINTS ***
CGPoint kbPoint = CGPointZero; // ?!?! Point on keyboard of the oneChar-key.
[UIView animateWithDuration: duration
animations: ^{
self.fingerView.center = kbPoint;
}
completion: ^(BOOL finished) {
// *** MAIN QUESTION ***
[self fakeTapEventOnKeyboard: oneChar]; // ?!?! How to do this?
}
];
}
}
EDIT: To clarify further, the behaviour I want is, when I call fakeTapEventOnKeyboard, I want iOS to behave as if the user had tapped that key. Specifically, the key should highlight (including the little popup-key graphic), make the key-tapped sound and type the key into the firstResponder field, if any.
I have a UIWebView that displays a generated html table. When the user taps on a cell in the html table, my app needs to know which cell they've tapped, and the (x,y) coordinate of the tap location so I can display a popover at that point.
I've implemented shouldStartLoadWithRequest in my UIWebView delegate. In my web page, I've embedded javascript code that captures the touch event and passes what should be the (x,y) coordinate of the touched point in a URL request as follows:
var x, y;
function init()
{
// Add an event listener for touch events - set x and y to the coordinate of the touch point
document.addEventListener('touchstart', function(event) {
x = event.touches[0].clientX;
y = event.touches[0].clientY;
}, false);
}
function cellTapped(event)
{
window.location.href="file://myapp/dostuff?x=" + x + "&y=" + y;
}
In my html table, each cell gets an onclick event that calls cellTapped():
<td onclick="cellTapped(event)">...</td>
So whenever the user touches anywhere in the UIWebView, I get the coordinate of the touch point, which I save off in x and y. If they touch within one of the table cells, I receive the touch event (which sets x and y), then cellTapped() gets called and I set window.location.href, passing the (x,y) coordinate into my app.
This all works beautifully. Unless the user has zoomed or scrolled the UIWebView. When they zoom or scroll, the x and y coordinates I'm getting from event.touches[0].clientX and event.touches[0].clientY are off by some varying number of pixels (varies with the amount of zoom and how far up/down or left/right the web view is scrolled).
Is there some way to determine the zoom ratio and scroll position of the web view so that I can adjust my x and y coordinates accordingly? The zoomScale and contentOffset properties from UIScrollView do not seem to be exposed in UIWebView.
Use UIGestureRecognizerDelegate method:
Add UIGestureRecognizerDelegate in declaration file (i.e. your .h file)
Step 1: Just set the delegate of gestureRecognizer: (in .m file)
UITapGestureRecognizer *webViewTapped = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapAction:)];
webViewTapped.numberOfTapsRequired = 1;
webViewTapped.delegate = self;
[webView addGestureRecognizer:webViewTapped];
[webViewTapped release];
Step 2: Override this function: (in .m file)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Step 3: Now implement the tapAction function:
- (void)tapAction:(UITapGestureRecognizer *)sender
{
CGPoint point = [sender locationInView:self.view]; // get x and y from here
}
EDIT: In iOS 5 and above, the scrollView property of UIWebView is exposed and accessible so this becomes a non-issue. In my case, I still need to support devices running iOS 4 (believe it or not...), so the following solves it for older versions.
By looping through the subviews of my UIWebView, I can find the underlying UIScrollView, then use its zoomScale and contentOffset properties to find the zoom and scroll position:
for (UIView *view in myWebView.subviews)
{
if ([view isKindOfClass:[UIScrollView class]])
{
// Get UIScrollView object
scrollview = (UIScrollView *) view;
// Find the zoom and scroll offsets
float zoom = scrollView.zoomScale;
float xOffset = scrollView.contentOffset.x;
float yOffset = scrollView.contentOffset.y;
}
}
I don't know if Apple would approve of this for app store submission, since I assume they had their reasons for not exposing the underlying UIScrollView object, but it does solve my problem. My app is distributed under an Enterprise license anyway, so app store submission isn't an issue for me.
I am using content editable html loaded in uiwebview. I need the code to set the cursor position when the keyboard is hidden/shown.
Currently when i click on webview keyboard comes up but the content gets hidden behind the keyboard. Same happens when i keeps pressing on return key the cursor/text goes behind the webview or is not visible.
For head start, i need the functionality like used in iPad Evernote application. In that you can see cursor never goes behind the keyboard, it always starts above the keyboard.
I'm using javascript for this. I'm using a class to keep the code little more organized (so you'll see some this in the code), but that's not necessary.
// this is used to get the current coordinates of the selection - not very efficient, so it shouldn't be called too often
this.updateOffset = function() {
try{
var sel = window.getSelection();
range = sel.getRangeAt(0);
if(this.tmpSpan==null){
this.tmpSpan = document.createElement('span');
}
range.insertNode(this.tmpSpan);
this.yOffset = this.tmpSpan.offsetTop;
this.xOffset = this.tmpSpan.offsetLeft;
this.tmpSpan.parentNode.removeChild(this.tmpSpan);
}
catch(exc){
log('updateOffset:' + exc.toString());
}
}
// eContent is the div with 'contenteditable', while visibleHeight is an int, set from objective-c (depending on where the webview is positioned, keyboard height and screen height)
this.scrollToVisible = function(){
try {
if(this.eContent.clientHeight>this.visibleHeight){
this.updateOffset();
if(this.yOffset<window.pageYOffset){
window.scrollTo(0, this.yOffset);
}
else if(this.yOffset-window.pageYOffset>this.visibleHeight){
window.scrollTo(0, this.yOffset-this.visibleHeight);
}
}
}
catch (exc){
log('scrollToVisible: ', exc.toString());
}
}
In objective-c I'm setting the visibleHeight during keyboard showing up, and afterwards call scrollToVisible when keyboard has finished showing.
-(void)setVisibleHeight:(int)height{
[self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"docState.visibleHeight=%d", height]];
}
-(void)scrollToVisible{
[self stringByEvaluatingJavaScriptFromString:#"docState.scrollToVisible()"];
}
scrollToVisible is also called on the javascript events: onkeyup, onpaset, oncut, which fixes the issue when pressing 'return' or wrapping on multiple lines.
In case you decide to go this way, you'll need to be very careful when you scroll through javascript, otherwise it may cause some issues with UIWebview control (e.g: placing the cursor at the wrong positions, moving cursor automatically on the top of the document etc.)
Edit
Some clarification regarding the visibleHeight. From what I can remember, I used this because I wasn't able to get the actual visible height from javascript (document.body.clientHeight would also include the area behind the keyboard).
Since I'm presenting the UIWebView in full screen, I'm setting the visible height as follows:
- (void)keyboardWillShow:(NSNotification *)notification {
...
NSDictionary *userInfo = [notification userInfo];
NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValue CGRectValue];
CGRect kbRect = [self.window convertRect:keyboardRect fromView:nil];
_kbRect = kbRect;
CGPoint sorigin = [self.superview convertPoint:self.frame.origin toView:nil];
int visibleHeight = _kbRect.origin.y-sorigin.y-_tlbInputAccessory.frame.size.height-lkPadBottom; // _tlbInputAccessory is a custom accessory view
[self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"docState.setVisibleHeight(%d)", height]];
...
}
Note that I'm calling this from a subclass of UIWebView, so self will represent the UIWebView control.