I'm going crazy. I'll try to move the ToolBar with its textfield when the key board is appearing. With the following code the view is really moving but the ToolBar stays and gets hidden by the keyboard:
- (void) liftMainViewWhenKeybordAppears:(NSNotification*)aNotification{
NSDictionary* userInfo = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
[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)];
[UIView commitAnimations];
}
I'm a beginner so please don't beat me up but I don't know the missing link to move and show the ToolBar with its textfield.
The toolbar and the textfield is created in the viewDidLoad method.
I figured out that the ToolBar itself has to move with the keyboard:
This prevents it from get hidden by the appearing keyboard:
When using a ToolBar in a NavigationController the following code should do the trick:
- (void) liftMainViewWhenKeybordAppears:(NSNotification*)aNotification
{
NSDictionary* userInfo = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardFrame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
[self.navigationController.toolbar setFrame:CGRectMake(self.navigationController.toolbar.frame.origin.x,
self.navigationController.toolbar.frame.origin.y - keyboardFrame.size.height +self.navigationController.toolbar.frame.size.height,
self.navigationController.toolbar.frame.size.width,
self.navigationController.toolbar.frame.size.height)];
[UIView commitAnimations];
}
All the other necessary code is pretty well described HERE.
self.view does not contain the toolbar, you have to move the toolbar separately ...
Related
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);
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);
}];
}
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 am making a chat that functions similar to the one below:
When a user clicks the message bubble, I need it to raise both the UITextField AND the UITableView (with the table view above the text-box of course). And similarly, when they send or retract the message, it should go back down to what it was.
I tried the solution posted here
Two notifications:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHideOrShow:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHideOrShow:) name:UIKeyboardWillShowNotification object:nil];
And the actual function:
- (void)keyboardWillHideOrShow:(NSNotification *)note
{
NSDictionary *userInfo = note.userInfo;
NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardFrameForTextField = [self.myTextField.superview convertRect:keyboardFrame fromView:nil];
CGRect newTextFieldFrame = self.myTextField.frame;
newTextFieldFrame.origin.y = keyboardFrameForTextField.origin.y - newTextFieldFrame.size.height;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
self.myTextField.frame = newTextFieldFrame;
} completion:nil];
}
But it has two problems:
I'm not sure how to raise the tableview on top of the keyboard
When the keyboard goes back down, the input box disappears entirely.
This might help....Cant take credit for it but for the life of me I cant remember where it came from...helped me with a project at one point though so this is how I used it.
This will move the view up and down when the keyboard is called/dismissed based on a BOOL value YES or NO. This way also allows you to have a bit more control over other aspects of it.
- (void) animateTextField: (UITextField*) textField up: (BOOL)up
{
const int movementDistance = 100;
const float movementDuration = 0.3f;
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
And then to implement it:
-(IBAction)goingup:(id)sender
{
//Bounces the text field up for editing
[self animateTextField: yourtextfield up: YES];}
}
-(IBAction)backdown:(id)sender
{
//Bounces it back when keyboard is dismissed
[self animateTextField: yourtextfield up: NO];
}
Connect the actions to your text fields Editing did begin and Editing did end outlets and you're set.
Hope that helps.