iOS Keyboard Location and Orientation - iphone

I'm relatively new to iOS SDK, and I'm experiencing a very bizarre issue regarding the device keyboard location and orientation for an app I'm working on. The problem is that if the keyboard is open while the user multi-tasks or the app goes into background, after the user comes back to the app, the keyboard will be be displaced (with UIKeyboardWillChangeFrameNotification being raised), but in an incorrect orientation and location.
Sometimes the keyboard shows up completely off the screen too, which is completely undesired behaviour.
My questions are:
What is the position and orientation of the keyboard dependant on? How is it controlled by iOS?
Is there a way to detect when the keyboard is being displayed off-screen regardless of the device type and screen size? I'm thinking it would be doable by tracking UIKeyboardWillChangeFrameNotification or UIKeyboardWillShowNotification.
How would I reset/set the location and orientation of the keyboard prior to displaying it? Is this even possible?

From the documentation:
Use the keys described in “Keyboard Notification User Info Keys” to get the location and size of the keyboard from the userInfo dictionary.
Keys used to get values from the user information dictionary of keyboard notifications:
NSString * const UIKeyboardFrameBeginUserInfoKey;
NSString * const UIKeyboardFrameEndUserInfoKey;
NSString * const UIKeyboardAnimationDurationUserInfoKey;
NSString * const UIKeyboardAnimationCurveUserInfoKey;

1.) Keyboard is a UIWindow, the position is dependent on the Application's Main Window.
2.) What you could do is, upon the one of the notifications UIKeyboardWillShowNotification or UIKeyboardWillChangeFrameNotification method firing, loop through the windows subviews to locate the Keyboard. In one of my applications I needed to add a subview to the keyboard. For your case you can get the frame by doing this:
//The UIWindow that contains the keyboard view - It some situations it will be better to actually
//iterate through each window to figure out where the keyboard is, but In my applications case
//I know that the second window has the keyboard so I just reference it directly
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
//Because we cant get access to the UIPeripheral throught the SDK we will just use UIView.
//UIPeripheral is a subclass of UIView anyways
UIView* keyboard;
//Iterate though each view inside of the selected Window
for(int i = 0; i < [tempWindow.subviews count]; i++)
{
//Get a reference of the current view
keyboard = [tempWindow.subviews objectAtIndex:i];
//Assuming this is for 4.0+, In 3.0 you would use "<UIKeyboard"
if([[keyboard description] hasPrefix:#"<UIPeripheral"] == YES) {
//Keyboard is now a UIView reference to the UIPeripheral we want
NSLog(#"Keyboard Frame: %#",NSStringFromCGRect(keyboard.frame));
}
}
3.) Not completely sure this is possible, but with the supplied code I gave you. keyboard is now casted to a 'UIView', which you can apply your own transforms to.
This might not be the most elegant solution, but it works well for my case.
Hope this Helps !

Related

iPhone/iPad Keyboard Dimming

I am writing a universal app that will be used primarily at night. I will need to display a keyboard but do not want the light colors of the keyboard to blind the user and/or spoil their night vision. I do not want to have to go through the trouble to creating a custom keyboard so I thought a solution might be to place a UIView over the keyboard and give it a black background color with an alpha of 0.5 or something however, I can not figure out how to get a UIView to cover the keyboard. Does anyone know how to do this? Does Apple allow this?
The keyboard is found as a subview of a new window that is added when it appears. Finding it is a little hacky and fragile (will need checking at new iOS versions, as it has changed before) but it does work and it is allowed (I do exactly this for a night mode in an app that is on the app store).
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1]; // This assumes you aren't adding any new windows yourself
for(UIView *keyboard in tempWindow.subviews)
{
if([[keyboard description] hasPrefix:#"<UIPeripheralHost"] == YES) // This was different in an earlier version of iOS, and may well change again in the future!
{
[keyboard addSubview:maskView];
break;
}
}
This is done inside the method that responds to the UIKeyboardDidShowNotification object. I've not tried it on the iPad, this is iPhone code only.
The mask view is, as you say, just a plain view with a black background and some transparency. You can also use the alert keyboard style which gives a black space in between the keys.
This method does not prevent the little key flashes (the larger keys that pop up when you tap a key) from being at full brightness, unfortunately.
try applying the required changes on inputView property of UITextFiled/UITextArea (the one being used).

I'm just beginning Objective-C and I'm developing an iPhone app. I need some help with Objective-C

I'm 14 and developing my second iOS app: an iPhone version of the web-based chatroom I created for my school. I have very little knowledge of Objective-C and I need some help. This is a very basic app, where I have a UIWebView and a tool bar at the bottom of the view. The toolbar contains a text field and a "Send" button. I have the UIWebView working and pointing to the correct site, but I need two basic things:
1. I need the toolbar to reposition itself to the top of the keyboard when the text box is tapped, also resizing the UIWebView for the correct space.
and
2. I need to find a way to post the contents of my text field to my PHP script online when the "Send" button is tapped or the "Send" key on the keyboard is pressed.
Any help would be much appreciated!
Edit: Here are some screenshots of the app.
App screenshots.
You'll want to take a look at "Managing The Keyboard".
In essense what you want to do is have the delegate of the textfield deal with the keyboard notification "UIKeyboardWillShowNotification", and use the info which it will supply to move the toolbar into place, possibly with an animation.
---UPDATE---
Looking around a little, I found this:
iPhone Keyboard Covers UITextField
Lots of stuff to answer here!
Repositioning the toolbar
To reposition the toolbar you'll need to do a few things:
Get notified when the user starts using it
Resize your webview and move your toolbar
In order to get notified when the user taps on your text field you will need to:
Implement the UITextFieldDelegate protocol in your controller (most likely the main view controller).
Implement the delegate method -textFieldDidBeginEditing:.
Set your controller object as the text field's delegate.
UITextFieldDelegateProtocol Reference should explain this.
To resize your controls you will need to have them declared as IBOutlets and hook them up in interface builder. Your best bet for this is to read the Interface Builder Quick Start Guide.
Sending the data
Sending the data is going to be the trickier bit. A couple of things you could do:
Cheat and send the data as "GET" data by using a method like NSString's -initWithContentsOfURL: (something like this:)
NSString *chatString = [textField stringValue]; //get the chat string
NSString *encodedString = [chatString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; //URL-encode any special characters
NSString *urlToRequest = [NSString stringWithFormat:#"http://mysite.com/chat.php?message=%#", encodedString];
NSURL *requestURL = [NSURL URLWithString:urlToRequest];
NSString *urlResult = [NSString stringWithContentsOfURL:requestURL];
By doing it this way you will be able to get the message in your php script like so:
$encoded_message = $_GET['message'];
$message = urldecode($encoded_message);
This is not the most robust way but for a high school project it should probably be fine.
The more robust way you could do it is by using the cocoa libraries intended for this. I won't delve into these details as it is quite complex and Apple's own developer documentation does a much better job of explaining it: URL Loading System Programming Guide
Edit: As per Hack Saw's post, using NSNotification to determine when the keyboard will show is better. By doing things the delegate way as I've described, you will only be notified when that particular text field is selected. Documentation on managing the keyboard can be found here: Text, Web, and Editing Programming Guide for iOS
This is a quick unfancy way to do move the toolbar up. I'm sure you'll be able to adapt it to your needs.
First you have to register for the keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
and then you move the toolbar up. Like this.
- (void)keyboardWillShow:(NSNotification *)notification {
if (keyboardShown) {
return;
}
NSDictionary* info = [notification userInfo];
// Get the size of the keyboard.
NSValue* aValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
CGRect currentFrame = self.toolbar.frame;
currentFrame.origin.y = currentFrame.origin.y - keyboardSize.height;
[UIView beginAnimations:#"ShowKeyboard" context:NULL];
[UIView setAnimationCurve:[[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
self.toolbar.frame = currentFrame;
[UIView commitAnimations];
keyboardShown = YES;
}
of course you have to create another method that will hide the keyboard, but this is basically the same as show keyboard, so I'll omit it.
To make things a little bit more easy you could make the toolbar and the webview subviews of a "content" view. You would then resize the height of the contentview and autoresizing will take care of the rest.
Oh and you should not resize the view just because of textFieldDidBeginEditing:. I don't know for the iphone, but it's possible to connect an external keyboard to the ipad. And you would resize the view without the keyboard showing up, leaving a big blank frame at the bottom.

iPhone app entering back into foreground shifts the view back to its origins and keyboard is still visible

I'm currently working on an iPhone 4 app with a registration view. The users can focus into a UITextField and I have code that will shift the view upwards to prevent the keyboard from covering up the textfield. But if the app is backgrounded and brought back into the foreground again, the keyboard is still up, the textfield is still in focus, but the view is now shifted back down in its original state. This covers up the textfield.
What's going on? How do I either make the view stay put or hide the keyboard when the app is brought back into the foreground?
UPDATE:
-Any changes for this on the new iOS5?
you could try doing something in applicationDidEnterBackground in your app delegate like
NSLog(#"%#", [self.viewController.YOURTEXTFIELD isFirstResponder]);
if ([self.viewController.YOURTEXTFIELD isFirstResponder]) {
[self.viewController.YOURTEXTFIELD resignFirstResponder];
}
the "isFirstResponder" checks to see if the keyboard is currently being used in this view and returns YES if it is and NO if it isn't.
The NSLog is there just so you know what is getting passed into the if statement.
I've next solution:
In AppDelegate
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// 1. get access to ViewController which is on top
// In my case, I have navigation controller in root
UIViewController* current_controller = [self.rootNavController.viewControllers lastObject];
// 2. loop all uitextfield.
for (UITextField* o_txt in [current_controller.view subviews]) {
[o_txt resignFirstResponder];
}
}
Look's like "hot fix" )

Show iPhone soft keyboard even though a hardware keyboard is connected

My iPad app uses an external "device" that acts as a hardware keyboard. But, at some point in the settings, I need to input text and I can't use the "device" ("device" is not a keyboard).
So, is there any way to force pop the soft keyboard even thought I have a hardware keyboard connected?
Yes. We've done this in a few of our apps for when the user has a Bluetooth scanner "keyboard" paired with the device. What you can do is make sure your textField has an inputAccessoryView and then force the frame of the inputAccessoryView yourself. This will cause the keyboard to display on screen.
We added the following two functions to our AppDelegate. The 'inputAccessoryView' variable is a UIView* we have declared in our app delegate:
//This function responds to all textFieldBegan editing
// we need to add an accessory view and use that to force the keyboards frame
// this way the keyboard appears when the scanner is attached
-(void) textFieldBegan: (NSNotification *) theNotification
{
UITextField *theTextField = [theNotification object];
// NSLog(#"textFieldBegan: %#", theTextField);
if (!inputAccessoryView) {
inputAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, navigationController.view.frame.size.width, 1)];
}
theTextField.inputAccessoryView = inputAccessoryView;
[self performSelector:#selector(forceKeyboard) withObject:nil afterDelay:0];
}
//Change the inputAccessoryView frame - this is correct for portrait, use a different
// frame for landscape
-(void) forceKeyboard
{
inputAccessoryView.superview.frame = CGRectMake(0, 759, 768, 265);
}
Then in our applicationDidFinishLaunching we added this notification observer so we would get an event anytime a text field began editing
//Setup the textFieldNotifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textFieldBegan:) name:UITextFieldTextDidBeginEditingNotification object:nil];
Hope that helps!
There’s no way to do this with the current SDK. Please let Apple know via the Bug Reporter.
The solutions here didn't work on iOS 13 or aren't App Store compatible so I solved the problem by creating my own soft keyboard. It is pretty basic but works. Feel free to contribute!
Project on Github
All you have to do is add SoftKeyboardView.swift to your project and somewhere (e.g. appDidFinishLaunching) hit the singleton:
Usage:
SoftKeyboardManager.shared.disabled = false
Since I have the same problem, the closest solution I have found is to use Erica Sadun's app called KeysPlease which is available via cydia and modmyi. It's description is "Use soft kb even when connected to a BT kb.".
Additionally I have found that if you have a physical keyboard also attached, in my case via the iPad keyboard doc, you can bring up the keyboard using a key which seems to map to the eject key on a bluetooth keyboard. Perhaps there is a way to inject this key as if it was pressed on an attached keyboard?
I really wish there was a more official coding solution to this.
When my app connect bluetooth device, keyboard wouldn't show.I try set force the frame of the inputAccessoryView as Brian Robbins say. It didn't work.
Then I use a stupid way to solve.I found when I click textfield or textview one more time, keyboard will show.
So I just need to simulate touch in textfield or textview once , it works.
If you want to do some simulate touch, check this.
https://github.com/HUYU2048/PTFakeTouch

OpenFlow AFItem UIImageView touchesBegan

I'm trying to use the OpenFlow project inside of my application.
My target is; when the user tab to any flow item which currently UIImageView according to OpenFlow's AFItemView, it will be zoom-in in the screen (with/without animation) and then user will be able to close and get back to cower flow view in the app.
I didn't get the tocuhesBegan event when I used the default OpenFlow library, then I saw this line
self.multipleTouchEnabled = NO;
self.userInteractionEnabled = NO;
self.autoresizesSubviews = YES;
in the AFOpenFlowView.m, when I change self.userInteractionEnabled = NO; to self.userInteractionEnabled = YES; I'm getting the touchesBegan event in the AFItemView.m that it already implement UIView, but flow doesn't work when I apply to this change.
I'm wondering where is the my mistake ?
Any help and example code would be appreciated.
Edit :
Let me explain my goal;
The target is user will open OpenFlow the scroll images with touch then when the touched any image that inside of the OpenFlow view, selected image will be come with zoom-in or flip or sth. animation. When the user touch to close icon which will be right side of the opened image, screen will be get back to the OpenFlow main screen, I did not find any solution to it on OpenFlow project. It's really urgent.
Regards
I've written this answer before: How to flick through a deck of cards?
The summary:
Once hitTest:withEvent: returns a non-nil value, it's over (by default); that view "owns" the touch (see UITouch.view). Only that view gets touchesBegan/Moved/Ended/Cancelled:withEvent: callbacks.
The touches are being grabbed by AFItemView, so AFOpenFlowView never gets touch events. It may be easier to add the necessary touch-handling to AFOpenFlowView instead.
Alternatively, you can implement touch-forwarding in AFOpenFlowView. It's a bit tricky to get right.