UITextField moving when keyboard will block it - iphone

I am trying to make it so that when you click the email field and the keyboard pops up it would move the view up. But right now with this code it moves the view up no matter what textfield I click. Also I cant get the keyboard to dismiss. Not sure how to set this code to only scroll to the active field?
code:
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.emailField.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, self.emailField.frame.origin.y-kbSize.height);
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
I have a view that looks like this (it is on a scrollview)

For this you can ignore the keyboard show/hide notifications and just use the UITextFieldDelegate protocol:
– (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if([textField isEqual:self.emailTextField]){
// scroll up
}
return true;
}
– (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
if([textField isEqual:self.emailTextField]){
// scroll back to start
}
return true;
}

– (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if([textField isEqual:YourTextfieldName])
{
}
return true; // return true is needed.
}
– (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
if([textField isEqual:YourTextfieldName])
{
}
return true; //return true is needed.
}

Related

Why does the view scroll up when keyboard is present for a textview but not for a textfield?

I have a textfield and a textview in a scroll view. When I begin to edit the textview the view scrolls up appropriately so the keyboard does not hide the text. The textfield, however, does not scroll up but is hidden by the keyboard. I have set the delegates of the textfields and textviews to the view controllers. The code I have so far is below. Thanks for the help in advance.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
kbRect = [self.view convertRect:kbRect toView:nil];
CGSize kbSize = kbRect.size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
pageScrollView.contentInset = contentInsets;
pageScrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
[pageScrollView setContentOffset:scrollPoint animated:YES];
}
}
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
pageScrollView.contentInset = contentInsets;
pageScrollView.scrollIndicatorInsets = contentInsets;
}
michael tyson created TPKeyboardAvoiding which is very easy to use you can get it from github. https://github.com/michaeltyson/TPKeyboardAvoiding
I do not know why it works for your textview, but for a scrollview with textfields I am doing this manually via
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWillBeShown:(NSNotification*)aNotification
{
if(keyboardShown) return;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
NSDictionary* info = [aNotification userInfo];
// Get the size of the keyboard.
NSValue* keyboardFrameValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRectWrtScreen = [keyboardFrameValue CGRectValue];
CGRect keyboardRectWrtView = [scrollView convertRect:[[scrollView window] convertRect:keyboardRectWrtScreen fromWindow:nil] fromView: nil];
float keyboardHeight = keyboardRectWrtView.size.height;
scrollView.frame = CGRectMake(scrollView.frame.origin.x, scrollView.frame.origin.y, scrollView.frame.size.width,scrollView.frame.size.height-keyboardHeight);
if(activeTextField) {
CGRect rect = [contentView convertRect:[activeTextField bounds] fromView:activeTextField];
rect.origin.y -= 25;
rect.size.height += 50;
[scrollView scrollRectToVisible:rect animated:YES];
}
[UIView commitAnimations];
keyboardShown = YES;
}
as you see, I am manually moving the scroll view to the visible part, then ensuring that the text field is in the center of the scroll view.

Generic UITableView keyboard resizing algorithm

I've searched a lot for code that resizes the table view to accomodate for keyboard showing and hiding, but almost every single post i came across assumes that the table view is taking the entire view of its view controller. I have an iPad application where the table view is only taking part of the screen. What's the correct way to resize the table view in this case? (all the code in the posts i've mentioned above fails)
The following code does what you want and works with any device and any layout. The code is courtesy of the Sensible TableView framework (with permission to copy and use).
- (void)keyboardWillShow:(NSNotification *)aNotification
{
if(keyboardShown)
return;
keyboardShown = YES;
// Get the keyboard size
UIScrollView *tableView;
if([self.tableView.superview isKindOfClass:[UIScrollView class]])
tableView = (UIScrollView *)self.tableView.superview;
else
tableView = self.tableView;
NSDictionary *userInfo = [aNotification userInfo];
NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [tableView.superview convertRect:[aValue CGRectValue] fromView:nil];
// Get the keyboard's animation details
NSTimeInterval animationDuration;
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
UIViewAnimationCurve animationCurve;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
// Determine how much overlap exists between tableView and the keyboard
CGRect tableFrame = tableView.frame;
CGFloat tableLowerYCoord = tableFrame.origin.y + tableFrame.size.height;
keyboardOverlap = tableLowerYCoord - keyboardRect.origin.y;
if(self.inputAccessoryView && keyboardOverlap>0)
{
CGFloat accessoryHeight = self.inputAccessoryView.frame.size.height;
keyboardOverlap -= accessoryHeight;
tableView.contentInset = UIEdgeInsetsMake(0, 0, accessoryHeight, 0);
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, accessoryHeight, 0);
}
if(keyboardOverlap < 0)
keyboardOverlap = 0;
if(keyboardOverlap != 0)
{
tableFrame.size.height -= keyboardOverlap;
NSTimeInterval delay = 0;
if(keyboardRect.size.height)
{
delay = (1 - keyboardOverlap/keyboardRect.size.height)*animationDuration;
animationDuration = animationDuration * keyboardOverlap/keyboardRect.size.height;
}
[UIView animateWithDuration:animationDuration delay:delay
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{ tableView.frame = tableFrame; }
completion:^(BOOL finished){ [self tableAnimationEnded:nil finished:nil contextInfo:nil]; }];
}
}
- (void)keyboardWillHide:(NSNotification *)aNotification
{
if(!keyboardShown)
return;
keyboardShown = NO;
UIScrollView *tableView;
if([self.tableView.superview isKindOfClass:[UIScrollView class]])
tableView = (UIScrollView *)self.tableView.superview;
else
tableView = self.tableView;
if(self.inputAccessoryView)
{
tableView.contentInset = UIEdgeInsetsZero;
tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}
if(keyboardOverlap == 0)
return;
// Get the size & animation details of the keyboard
NSDictionary *userInfo = [aNotification userInfo];
NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [tableView.superview convertRect:[aValue CGRectValue] fromView:nil];
NSTimeInterval animationDuration;
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
UIViewAnimationCurve animationCurve;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
CGRect tableFrame = tableView.frame;
tableFrame.size.height += keyboardOverlap;
if(keyboardRect.size.height)
animationDuration = animationDuration * keyboardOverlap/keyboardRect.size.height;
[UIView animateWithDuration:animationDuration delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{ tableView.frame = tableFrame; }
completion:nil];
}
- (void) tableAnimationEnded:(NSString*)animationID finished:(NSNumber *)finished contextInfo:(void *)context
{
// Scroll to the active cell
if(self.activeCellIndexPath)
{
[self.tableView scrollToRowAtIndexPath:self.activeCellIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
[self.tableView selectRowAtIndexPath:self.activeCellIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
Notes:
a. The above two methods have been added to the notification center using the following code:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
b. The ivars used above has been declared like this:
BOOL keyboardShown;
CGFloat keyboardOverlap;
c. 'self.activeCellIndexPath' is always set to the indexPath of the cell owning the currently active UITextField/UITextView.
Enjoy! :)
I've found the easiest solution to be this one(I'm not fan of using subviews for this kind of stuff):
register for keyboard frame change notification(idealy register in viewWillAppear: and unregister in viewWillDisappear:):
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil];
and then in method:
- (void)keyboardDidChangeFrame:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect kbIntersectFrame = [window convertRect:CGRectIntersection(window.frame, kbFrame) toView:self.scrollView];
kbIntersectFrame = CGRectIntersection(self.bounds, kbIntersectFrame);
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbIntersectFrame.size.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}
or if You want to get rid of the "jump" after changing contentInset:
- (void)keyboardDidChangeFrame:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect kbIntersectFrame = [window convertRect:CGRectIntersection(window.frame, kbFrame) toView:self.scrollView];
kbIntersectFrame = CGRectIntersection(self.scrollView.bounds, kbIntersectFrame);
// get point before contentInset change
CGPoint pointBefore = self.scrollView.contentOffset;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbIntersectFrame.size.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
// get point after contentInset change
CGPoint pointAfter = self.scrollView.contentOffset;
// avoid jump by settings contentOffset
self.scrollView.contentOffset = pointBefore;
// and now animate smoothly
[self.scrollView setContentOffset:pointAfter animated:YES];
}
The simple solution is to add my extension UIViewController+Keyboard.swift to your project, with a single line setupKeyboardNotifcationListenerForScrollView(tableView) it will auto resize automatically. No need to subclass anything, just an extension! Its open source at SingleLineKeyboardResize
Simple solution - register to receive keyboard notifications on init or viewDidLoad with:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
then when the notification is received, you can use the given rect of the keyboard to adjust the frame of your tableView:
- (void)keyboardWillShow:(NSNotification *)notification
{
// Get the size of the keyboard.
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect newTableFrame = _myTableView.frame;
//Here make adjustments to the tableview frame based on the value in keyboard size
...
_myTableView.frame = newTableFrame;
}
- (void)keyboardWillHide:(NSNotification *)notification
{
//Here change the table frame back to what it originally was.
}
Check out this project, it's drag and drop so just declare the tablview as type TPKeyboardAvoidingTableView
Here is the keyboard method:
func keyboardControl(notification: NSNotification, isShowing: Bool) {
var userInfo = notification.userInfo!
let keyboardRect = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue
let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey]!.unsignedIntValue
let convertedFrame = self.view.convertRect(keyboardRect, fromView: nil)
let heightOffset = self.view.bounds.size.height - convertedFrame.origin.y
let options = UIViewAnimationOptions(rawValue: UInt(curve) << 16)
let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue
//your UITableView bottom constrant
self.tableViewMarginBottomConstraint.constant = heightOffset
var contentInsets = UIEdgeInsetsZero
if isShowing {
contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardRect.size.height), 0.0)
}
UIView.animateWithDuration(
duration,
delay: 0,
options: options.union(.LayoutSubviews).union(.BeginFromCurrentState),
animations: {
self.listTableView.contentInset = contentInsets
self.listTableView.scrollIndicatorInsets = contentInsets
self.listTableView.scrollBottomToLastRow()
self.view.layoutIfNeeded()
},
completion: { bool in
})
}
Here is the UITableView extension:
extension UITableView {
func totalRows() -> Int {
var i = 0
var rowCount = 0
while i < self.numberOfSections {
rowCount += self.numberOfRowsInSection(i)
i++
}
return rowCount
}
var lastIndexPath: NSIndexPath {
get { return NSIndexPath(forRow: self.totalRows()-1, inSection: 0) }
}
func scrollBottomToLastRow() {
self.scrollToRowAtIndexPath(self.lastIndexPath, atScrollPosition: .Bottom, animated: false)
}
}
You can achieve what you're looking for by using IQKeyboardManager, it's a codeless library, you just have to add it to your Podfile: pod 'IQKeyboardManager' and that's it, it will hand the scrolling effect when the keyboard is shown even if the UITextField/UITextView is not part of a scrollView/tableView.

Japanese keyboard's height

I want to scroll up my form to let the keyboard under the UITextField. It works for English keyboard, but when i change to Japanese keyboard, my form only scroll up little. I debug and find out that the height of keyboard for two cases is difference.
I do as following
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
NSLog(#"kbSize.height=%0.1f", kbSize.height);
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) )
{
CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
And here is the result of info:
For ENGLISH keyboard: kbSize.height=216.0
For JAPANESE keyboard: kbSize.height=252.0
Is there anyone got this case? And can somebody help me to solve this problem?
Thank you.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardModeChange:) name:UITextInputCurrentInputModeDidChangeNotification object:nil];

Event for dismissing onscreen keyboard by clicking the keyboard button

I've been looking everywhere... maybe i'm not using the right searchwords since i do believe this is a common question.
Is there an event i can handle for when the user dismisses the keyboard by clicking the button to lower the keyboard.
i move a view up when a uitextfield becomes firstresponder but i want to move it down again when this button is tapped
Try using notifications. Add that to your viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
and then create a method called keyboardWillHide:
- (void)keyboardWillHide:(NSNotification *)notification {
//do whatever you need
}
Hope it helps
Check out the second paragraph in the "Managing Keyboard" section: http://developer.apple.com/library/ios/DOCUMENTATION/UIKit/Reference/UITextField_Class/Reference/UITextField.html
By using NSNotificationCenter you get Keyboard events.You can register for keyboard events in viewWillAppear and don't forget to unregister in viewWillDisapper.
We will use here two notifications :
UIKeyboardDidShowNotification apple docs
UIKeyboardDidHideNotification apple docs
You can do some thing like this:
(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"Registering for keyboard events");
// Register for the events
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector (keyboardDidShow:)
name: UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector (keyboardDidHide:)
name: UIKeyboardDidHideNotification
object:nil];
// Setup content size
scrollview.contentSize = CGSizeMake(SCROLLVIEW_CONTENT_WIDTH,
SCROLLVIEW_CONTENT_HEIGHT);//for e.g. (320,460)
//Initially the keyboard is hidden
keyboardVisible = NO;//in .h declare BOOL keyboardVisible;
}
-(void) viewWillDisappear:(BOOL)animated {
NSLog (#"Unregister for keyboard events");
[[NSNotificationCenter defaultCenter]
removeObserver:self];
}
-(void) keyboardDidShow: (NSNotification *)notif {
NSLog(#"Keyboard is visible");
// If keyboard is visible, return
if (keyboardVisible) {
NSLog(#"Keyboard is already visible. Ignore notification.");
return;
}
// Get the size of the keyboard.
NSDictionary* info = [notif userInfo];
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
// Save the current location so we can restore
// when keyboard is dismissed
offset = scrollview.contentOffset; //in .h declare CGPoint offset and UIScrollView *scrollview.;
// Resize the scroll view to make room for the keyboard
CGRect viewFrame = scrollview.frame;
viewFrame.size.height -= keyboardSize.height;
scrollview.frame = viewFrame;
CGRect textFieldRect = [activeField frame];//in .h UITextField *activeField;
textFieldRect.origin.y += 10;
[scrollview scrollRectToVisible:textFieldRect animated:YES];
// Keyboard is now visible
keyboardVisible = YES;
}
-(void) keyboardDidHide: (NSNotification *)notif {
// Is the keyboard already shown
if (!keyboardVisible) {
NSLog(#"Keyboard is already hidden. Ignore notification.");
return;
}
// Reset the frame scroll view to its original value
scrollview.frame = CGRectMake(0, 0, SCROLLVIEW_CONTENT_WIDTH, SCROLLVIEW_CONTENT_HEIGHT);
// Reset the scrollview to previous location
scrollview.contentOffset = offset;
// Keyboard is no longer visible
keyboardVisible = NO;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
hope would help you :)

avoid view when opening keyboard from a UITextView inside a UITableView with custom cell

I have a UIViewController that contains a UITableView with custom cells, inside the cell are UILabels, a couple of uneditable UITextView and one editable UITextView. Now, when I tap on one of the UITextView that is near the bottom or the bottom part of the table, the UITextView is covered by the keyboard. I've tried http://cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html which works great for textfield/textview but not working on the table with custom cell. Any help or suggestions how to go about this?
When your table view contains data entry fields like a UITextField or a UITextView and the table view is long enough to cover the screen, you will have a problem accessing data entry fields that are hidden by the keyboard.
To overcome this problem two solutions are:
The easiest and recommended way is to use a UITableViewController instead of UIViewController, which automatic make sure keypad won't hide the editable field (If possible use this approach to avoid U.I. adjustment inconvenience)
If you use a UIViewController and a UITableView as its subview. You can scroll your UI’s frame by observing the UIKeyboardWillShowNotification and UIKeyboardWillHideNotification
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil]; //Posted immediately prior to the display of the keyboard
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification object:nil]; //Posted immediately prior to the dismissal of the keyboard.
}
- (void)keyboardWillShow:(NSNotification *)aNotification
{
CGRect keyboardBounds = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardBounds.size.height, 0); //when keyboard is up, that time just bring your text filed above the keyboard
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, keyboardBounds.size.height, 0);
[self.tableView scrollToRowAtIndexPath:[self findIndexPathToScroll]
atScrollPosition:UITableViewScrollPositionTop
animated:YES]; //findIndexPathToScroll implementation not shown
[UIView commitAnimations];
}
- (void)keyboardWillHide:(NSNotification *)aNotification
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
self.tableView.contentInset = UIEdgeInsetsZero; //Once keyboard is hidden then bring back your table into your original position.
self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
[UIView commitAnimations];
}
registerForKeyboardNotifications - call this method when you load the UITableView, ie: viewDidLoad
findIndexPathToScroll - (Implementation not shown) Its your business logic to prepare IndexPath where table view should scroll
removeObserver 'UIKeyboardWillShowNotification' and 'UIKeyboardWillHideNotification' both in dealloc and viewDidUnload
I fixed the issue. Please see my solution below:
1. First declare a global varibale called "activeFileld"
#property(nonatomic,strong)id activeFiled;
2. Create a method called "registerForKeyboardNotifications"
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil]; //Posted immediately prior to the display of the keyboard
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification object:nil]; //Posted immediately prior to the dismissal of the keyboard.
}
3. Called the above method in viewWillAppear:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
//Register kryboard Notification
[self registerForKeyboardNotifications];
}
4. Call the Delegate method for UitextFieldd Or UitextView
- (void)textFieldDidBeginEditing:(UITextField *)sender {
self.activeField = sender;
}
- (void)textFieldDidEndEditing:(UITextField *)sender{
self.activeField = nil;
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
// save the text view that is being edited
_notes = textView.text;
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
// release the selected text view as we don't need it anymore
_activeField = nil;
}
5.
- (void)keyboardWillShow:(NSNotification *)notification
{
if([_activeField isKindOfClass:[UITextField class]]) {
NSDictionary* info = [notification userInfo];
NSLog(#"Dictionary %#",info);
CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
kbRect = [self.view convertRect:kbRect fromView:nil];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
CGRect aRect = self.view.frame;
aRect.size.height -= kbRect.size.height;
UITextField *textField = (UITextField*)_activeField;
if (!CGRectContainsPoint(aRect, textField.frame.origin) ) {
[self.tableView scrollRectToVisible:textField.frame animated:YES];
}
}else if([_activeField isKindOfClass:[UITextView class]]) {
NSDictionary* info = [notification userInfo];
NSLog(#"Dictionary %#",info);
CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
kbRect = [self.view convertRect:kbRect fromView:nil];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
CGRect aRect = self.view.frame;
aRect.size.height += kbRect.size.height;
UITextView *activeTextView = (UITextView*)_activeField;
if (!CGRectContainsPoint(aRect, textField.superview.superview.frame.origin) ) {
[self.tableView scrollRectToVisible:activeTextView.superview.superview.frame animated:YES];
}
}
}
// Called when the UIKeyboardWillHideNotification is received
- (void)keyboardWillHide:(NSNotification *)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
}
Two solutions:
Preferred: use a UITableViewController instead of a UIViewController as that one will automatically make sure that your keypad won't hide the editable field.
Hacky: How to make a UITextField move up when keyboard is present?
A simple solution. Implement the heightForFooter method, and let it return a value of (say) 100, and when you select the a cell in UITableView, they will simply slide up by that height, and the keyboard will not cover the view.
I've always used a two fold solution for this.
Resize table so it now fits in the smaller area.
Scroll to the cell we want visible. (we needed to re-size the table for this or you'd still wind up being unable to get to the last couple of cells in the table.)
To do this, I register keyboard show/hide events and act accordingly when they get called.
- (void)keyboardWillShow:(NSNotification *)note {
[self updateForKeyboardShowHide:note appearing:YES];
}
- (void)keyboardWillHide:(NSNotification *)note {
[self updateForKeyboardShowHide:note appearing:NO];
}
- (void)updateForKeyboardShowHide:(NSNotification *)note appearing:(BOOL)isAppearing {
// ignore notifications if our view isn't attached to the window
if (self.view.window == nil)
return;
CGFloat directionalModifier = isAppearing?-1:1;
CGRect keyboardBounds = [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGFloat animationDuration = [[note.userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
// figure out table re-size based on keyboard
CGFloat keyboardHeight;
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsPortrait(orientation))
keyboardHeight = keyboardBounds.size.height;
else
keyboardHeight = keyboardBounds.size.width;
[UIView animateWithDuration:animationDuration animations:^{
// resize table
CGRect newFrame = table.frame;
newFrame.size.height += [self calculateKeyboardOffsetWithHeight:keyboardHeight] * directionalModifier;
table.frame = newFrame;
} completion:^(BOOL finished){
// scroll to selected cell
if (isAppearing) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:textFieldInEdit.tag inSection:0];
[table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
}];
}
- (CGFloat)calulateKeyboardOffsetWithHeight:(CGFloat)keyboardHeight {
// This depends on the size and position of your table.
// If your table happen to go all the way to the bottom of
// the screen, you'll needs to adjust it's size by the whole keyboard height.
// You might as well ditch this method and inline the value.
return keyboardHeight;
// My table did not go to the bottom of the screen and the position was
// change dynamically so and there was long boring calculation I needed to
// do to figure out how much my table needed to shrink/grow.
}