I have a UIView with a UITextField placed at the bottom of the screen which I'd like to move up when a keyboard appears.
I have added keyboardFrameDidChange observer for getting notified whenever a keyboard appears/disappears. Here is the method :
-(void)keyboardFrameDidChange:(NSNotification*)notification{
NSDictionary* info = [notification userInfo];
CGRect kKeyBoardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
[bottomView layoutIfNeeded];
[UIView animateWithDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue] delay:0 options:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue] animations:^{
[bottomView setFrame:CGRectMake(0, kKeyBoardFrame.origin.y - bottomView.frame.size.height, 320, bottomView.frame.size.height)];
} completion:^(BOOL finished) {
[bottomView layoutIfNeeded];
NSLog(#"frame ** %f",self.bottomView.frame.origin.y);
}];
}
Here the frame of bottomView is changing but nothing happens in the UI. The bottomView just remains at the bottom. What might be the reason?
This sounds like an auto layout problem. If auto layout is on, then you should change the view's position by adjusting its constraints, not setting frames. Make an IBOutlet to the constraint between the text field and the bottom of superview (bottomCon in my example), and adjust it.
-(void)keyboardFrameDidChange:(NSNotification*)notification{
NSDictionary* info = [notification userInfo];
CGRect kKeyBoardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
[_bottomView layoutIfNeeded];
[UIView animateWithDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue] delay:0 options:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue] animations:^{
self.bottomCon.constant = kKeyBoardFrame.origin.y;
[_bottomView layoutIfNeeded];
} completion:^(BOOL finished) {
NSLog(#"frame ** %f",self.bottomView.frame.origin.y);
}];
}
Related
I have added code for pushing table view above keyboard. I have change the bottomLayout constraint of table view. But, he i set the constraint, there is an extra space above keyboard.
I have added sample code for keyboard showing notification.
- (void)keyboardWillShow:(NSNotification*)notification
{
CGRect rect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect rectInView = [self.view rect fromView:nil];
[UIView animateWithDuration:0.25 animations:^{
self.bottomLayoutConstraint.constant = rectInView.size.height;
[self.view layoutIfNeeded];
}];
}
After this i got the following output in the keyboard.
The keyboard info dictionary is returning incorrect numbers for the emoji keyboard height. If I click on the textfield it animates up the normal keyboard fine but when i click on the emoji's it still thinks the height is the standard keyboard. Why? And is there a way to get the alternate (emoji) keyboard height programatically. The constant 37 is a terrible hack that I put in to get it to work.
- (void)keyboardWillShow:(NSNotification *)notification {
if (!IS_SHOWING_KEYBOARD) {
IS_SHOWING_KEYBOARD=YES;
NSDictionary *userInfo = [notification userInfo];
CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
[self.view layoutIfNeeded];
self.commentTopLayout.constant -= keyboardSize.height;
self.commentBottomLayout.constant -= keyboardSize.height;
[UIView animateWithDuration:0.2f animations:^{
[self.view layoutIfNeeded];
}];
} else { //move him down, then up again. //clicked on emojis
NSDictionary *userInfo = [notification userInfo];
CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
[self.view layoutIfNeeded];
self.commentTopLayout.constant += keyboardSize.height;
self.commentBottomLayout.constant += keyboardSize.height;
[UIView animateWithDuration:0.2f animations:^{
[self.view layoutIfNeeded];
}];
[self.view layoutIfNeeded];
self.commentTopLayout.constant -= keyboardSize.height+37;
self.commentBottomLayout.constant -= keyboardSize.height+37;
[UIView animateWithDuration:0.2f animations:^{
[self.view layoutIfNeeded];
}];
}
}
I had the same problem. Just replace UIKeyboardFrameBeginUserInfoKey with UIKeyboardFrameEndUserInfoKey . :-)
I have a TableView inside a UIViewController created in Main.Storyboard.
The Y-position is 0 when initialized.
My problem is, when the keyboard shows, the Y-Position of the TableView doesn't change at all. The Y-position stays at 0. So the cells get's hidden behind the NavigationController.
The code so far:
-(void) keyboardWasShown:(NSNotification*)aNotification
{
if (kbIsShown == false) {
NSDictionary* info = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardFrame;
[[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardFrame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
NSLog(#"frame..%f..%f..%f..%f",self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
NSLog(#"keyboard..%f..%f..%f..%f",keyboardFrame.origin.x, keyboardFrame.origin.y, keyboardFrame.size.width, keyboardFrame.size.height);
[self.view setFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y - keyboardFrame.size.height, self.view.frame.size.width, self.view.frame.size.height)];
[chatTable setFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y + keyboardFrame.size.height + TABBAR_HEIGHT, self.view.frame.size.width, self.view.frame.size.height-keyboardFrame.size.height)];
[UIView commitAnimations];
NSLog(#"Visar sig");
kbIsShown = true;
}
}
The [chatTable setFrame:] doesn't do anything. The TableViews (chatTable) Y-position stays at 0. How can i change the Y-position of the Tableview so my content will be visible?
Note: [self.view setFrame...] does actually change the Y-position of the view. But the chatTable stays at 0.
In order to scroll your table view to desired row use:
[chatTable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
you should also set:
chatTable.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0);
The app I am building has a messaging/chat view controller that has a view with a textView and a button at the base of the view (tab bar is set to hidden). When the view loads, the view with those objects (the textView and the button) in it is at the base of the screen (like how it looks in the iMessage app when you go into a conversation)
Now when the textview is tapped on, obviously the keyboard moves up, and along with that I have managed to get the view to move up and sit right up on top of the keyboard (like when you go to type in a new text message).
Now what I am trying to do is get the view move up and down with the keyboard. As of right now it starts at the bottom. When keyboard goes up, that view is stuck at the bottom for a second or two and then just appears above the keyboard. Same goes for when the keyboard is dismissed.
I wish I could provide pictures but I guess my reputation is not quite cutting it
Is there a way I can match the transitions or animations of the two so they move together as if they are attached?
The view is initialized
//Create the keyboard UIView
self.keyboardView = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.frame.origin.y + self.view.frame.size.height - (self.navigationController.tabBarController.tabBar.frame.size.height), self.view.frame.size.width, 50)];
Selector used to move the view
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardFrameDidChange:) name:UIKeyboardDidChangeFrameNotification object:nil];
Selector implemented
- (void)keyboardFrameDidChange:(NSNotification*)notification{
NSDictionary* info = [notification userInfo];
CGRect kKeyBoardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
[self.keyboardView setFrame:CGRectMake(0, kKeyBoardFrame.origin.y - self.keyboardView.frame.size.height, 320, self.keyboardView.frame.size.height)];
self.myScrollView.contentSize = CGSizeMake(self.view.frame.size.width, self.myTableView.frame.size.height);
}
You can do this here is the keyboard notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
keyboardWasShown
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
double duration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
int curve = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
[UIView beginAnimations:#"foo" context:nil];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
CGRect rect=self.viewChatWindow.frame;
rect.size.height=self.viewChatWindow.frame.size.height-kbSize.height;
self.viewChatWindow.frame=rect;
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(scrollToLast)];
[UIView commitAnimations];
}
keyboardWillBeHidden
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
double duration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
int curve = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
[UIView beginAnimations:#"foo" context:nil];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
CGRect rect=self.viewChatWindow.frame;
rect.size.height=self.view.frame.size.height-rect.origin.y;
self.viewChatWindow.frame=rect;
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(scrollToLast)];
[UIView commitAnimations];
}
Just wrap your [keyboardView setFrame:...] in an animation block. You can get the keyboard's animation duration and curve from the notification object:
NSTimeInterval duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
[UIView animateWithDuration:duration delay:0 options:curve animations:^{
self.keyboardView.frame = ...;
} completion:nil];
Using UITextFieldDelegate
This will be your flag that the keyboard is gonna show up
-(void)textFieldDidBeginEditing:(UITextField *)textField{
//Animate like slide up.
[UIView animateWithDuration:0.3
animations:^{
//Use offset rather than contentSize
scrollView.contentOffset = CGPointMake(x,y);
}];
}
When your keyboard is dismissed (resignFirstResponder)
-(void)dismissKeyboard{
[self.view endEditing:YES];
[UIView animateWithDuration:0.3
animations:^{
scrollView.contentOffset = CGPointMake(0,0);
}];
}
I have a TextView. When keyboard appears, part of the TextView is hidden behind keyboard. So, I decrease its height by decreasing its bottom constraint(with its superview's bottom) so that user can scroll and see whole text.
But issue is when keyboard disappears its not resizing TextView's height to original. But when I tap on it, it shows whole text same as in first image.
How it looks normally :
How it looks when keyboard has appeared :
How it looks when keyboard has disappeared :
Now, if I tap on TextView it looks same as first image. i.e. resizes to have proper size :
Code : self.messageView is TextView.
// Called when keyboard is going to be displayed
- (void)keyboardWillShow:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
// get animation info from userInfo
NSTimeInterval animationDuration;
CGRect keyboardFrame;
[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardFrame];
// Save constant to set back later
self.bottomConstant = self.noticeMessageBottom.constant;
// Change bottom space constraint's constant
self.noticeMessageBottom.constant = keyboardFrame.size.height + 8.0f;
[UIView animateWithDuration:animationDuration delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.messageView setNeedsLayout];
[self.messageView layoutIfNeeded];
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
} completion:nil];
[self.messageView flashScrollIndicators];
}
// Called when keyboard is going to be hidden
- (void)keyboardWillHide:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
// get animation info from userInfo
NSTimeInterval animationDuration;
CGRect keyboardFrame;
[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardFrame];
// Reset contentOffset
self.messageView.contentOffset = CGPointZero;
// Change bottom space constraint's constant
self.noticeMessageBottom.constant = self.bottomConstant;
[UIView animateWithDuration:animationDuration delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.messageView setNeedsLayout];
[self.messageView layoutIfNeeded];
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
} completion:nil];
}
Update : I set background color to TextView and saw that height is changed properly but part of the text is not visible. It becomes visible when I tap on it.
Note : This happens only if TextView's contentOffset is (0,0).i.e user has not scrolled it. If user has scrolled it and contentOffset is not (0,0) then it works fine.
I just unchecked scroll enabled property of TextView in storyboard and its not giving that issue any more.