iOS 8 get keyboard height - ios

I'm having trouble reliably getting the actual height of the keyboard. I'm adding a custom toolbar that is meant to be placed directly above the keyboard. To do so with layout constraints, I've added a static space constraint between the bottom of the screen and the bottom of the toolbar. When the keyboard is displayed, I modify this constraint to be the height of the keyboard, which varies quite a bit in iOS 8.
To resize the spacer, I currently use the following method that gets fired on UIKeyboardDidShowNotification
-(void)keyboardDidShow:(NSNotification*)notification
{
CGFloat height = [[notification.userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].height;
self.shimConstraint.constant = height;
[self.view layoutIfNeeded];
}
This does resize the constraint correctly sometimes, but often the keyboard height returned is entirely incorrect. What is the best way to reliably get the height of the keyboard once it is displayed?
EDIT: The application allows the user to switch between a number of different input fields. Some of them have autocorrect disabled, so the autocorrect bar may or may not be hidden, and incorrect heights are returned when switching fields.

The way you are doing it is correct but you might want to use UIKeyboardFrameEndUserInfoKey instead of UIKeyboardFrameBeginUserInfoKey. The end user key is the frame of the keyboard when it is done animating and on the screen, thus you know it will be that frame, while the begin key might not always match what the keyboard frame will be when it is shown.
There might also need to be extra considerations on orientation of the device, I have not looked into that, but for portrait, it should work.

The correct way to do this is to use the inputAccesorryView property of the UITextField.
The inputAccessoryView is automatically added above the keyboard regardless of keyboard size.
As the documentation states:
The default value of this property is nil. Assigning a view to this property causes that view to be displayed above the standard system keyboard (or above the custom input view if one is provided) when the text field becomes the first responder. For example, you could use this property to attach a custom toolbar to the keyboard
See more information here
https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/InputViews/InputViews.html

You might need to do [self.view setNeedsLayout] instead of [self.view layoutIfNeeded].

Related

Get Keyboard size without showing it

I can get the keyboard's dimension after its displayed from the notification, BUT I would like to position my textFields so that I don't have to scroll them when the keyboard appears. To achieve this I should know the keyboard's dimension BEFORE it's even displayed.
Is this possible on iOS?
You can use a class where this all things are handled by default. Just you have to use scroll view for this.
TPKeyboardAvoidingScrollView
See if it's useful and fulfill your requirement.

UITextFieldViewModeWhileEditing change my TextField frame

I got an weird issue. Please help me in this case.I had a bottom View which contain a TextField like this image
When I type text in textfield, I want my bottom view move above the keyboard and be like this:
However, after typing one character, my bottom view will move back to this previous position
I found out that whenever I set
self.textField.clearButtonMode = UITextFieldViewModeWhileEditing;
my bottom view will move back to its previous position.
This is my source code link: https://github.com/duythuc28/ProblemUITextField
Thanks for your help.
First of all, change observers from UIKeyboardDidShowNotification to UIKeyboardWillShowNotification and from UIKeyboardDidHideNotification to UIKeyboardWillHideNotification. Second: don't change view's frame. You have bottom view's constraint to bottom (equal to 0); create outlet for this constraint and in method keyboardWillShow set it equal to keyboard height and in keyboardWillHide to 0.
You are using Autolayout, so you cannot set frame for the view. It should reset the constraint.
Or you can use third-party such as IQKeyboardManager to handle your keyboard event with worries free. IQKeyboardManager can be used in both ObjectiveC and Swift. It can also handle the appearance of the suggestion on keyboard (which I realize in your code that haven't handled yet) Here is the link: https://github.com/hackiftekhar/IQKeyboardManager

Resizing UITextView with UIView below

I can't understand how create something like this:
The idea is the UITextView is resizing. But how to resize it when user enter 100 rows? I need to check /n and then increment frame by lineHeight and frame of cell?
Suggest pls.
No need. The text view should be resized to fit the keyboard. After that it scrolls the text if there is more text than fits into the visible part.
The path of least resistance to getting what you're describing to work is to create a method that updates the frames of the UITextView and UIView when the keyboard goes up or down. You know when the keyboard goes up and down based on UIKeyboardWillShowNotification and UIKeyboardWillDisappearNotification. The notification contains a userInfo dictionary that specifies the y-coordinate of the keyboard with respect to your view controller's window. All you need to do is recalculate your frames subtracting the height of the keyboard (either something like 216 or 0). If you still have questions about this let me know, and I'd be happy to explain further.

Changing height of a custom inputView when device rotates

I made a custom keyboard view and linked it to the inputView property of a UITextField.
Is there a way to change the height of a custom inputView when orientation changes and have the frame change animated smoothly just like the system keyboard?
My keyboard size is 768x272 and when the device goes landscape the size becomes 1024x272, but I want to make it bigger like 1024x372. If I change the frame with the code below when I get UIDeviceOrientationDidChangeNotification, the change animation is not smooth.
textField.inputView.frame = CGRectMake(0,0,1024,372);
Per Apple documentation for UIResponder.inputView:
"If UIKit encounters an input view with a UIViewAutoresizingFlexibleHeight value in its autoresizing mask, it changes the height to match the keyboard."
So if you want customized height, you shouldn't specify UIVieAutoresizingFlexibleHeight mask.
After many experiments, I found the best answer to my own question. A short answer is change frame when you get UIKeyboardDidHideNotification.
Custom inputView is embedded in another view controlled by the system called UIPeripheralHostView.
So changing the custom inputView at wrong time is not reflected immediately or shows an ugly layout at best.
When the device rotates, the system briefly hides the keyboard, then performs a rotation animation of the keyboard from old orientation to new orientation. I think the animation block is inserted somewhere between two notifications UIKeyboardDidHideNotification and UIKeyboardWillShowNotification. These notifications are coupled with UIKeyboardWillChangeFrameNotification. The "frame" in this notification actually means the frame of UIPeripheralHostView.
So changing the frame of my input view when I get UIKeyboardDidHideNotification gives the system a chance to adjust the frame of UIPeripheralHostView before the animation starts, resulting in smooth transition from short keyboard to tall keyboard during orientation change.
This works in iOS 5. But Apple may change the practice in the future.

How lower the uitextview current position in landscape mode?

I have a scrollview which cointains a uitextfield, a uitextview and two label
The uitextfield and the two label don't scroll.
In portrait mode all works fine.
In landscape mode, I resize the scroll view in the way that the labels are not visible, only title and textview remains, but I have a problem when the user try to insert the text in the textview. The current position is under the title, so the user cannot see what he/she insert. I would lower it.
Using the autosizing masks in IB, don't change the situation: I have to make flexible only the uitextview.
What can I try?
I thought that scrollRangeToVisible could help me, but nothing.
Try using
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
or
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
in your view controller to place your uiTextView where you need it depending on the orientation. Change the textview's frame to something that works visually. I think the first method ignores IB's resizing masks, so you have to set coordinates for your objects' frames using CGRectMake. The second method will animate the rotation as per the resizing masks, but then will "all of a sudden" move the objects to where you specified their frames to be (again using CGRectMake).

Resources