I am working on a chat application similar to whatsapp etc. It has a tableview in view controller and a text field and button in the bottom toolbar. I came across the various question on sliding the view upwards and using this link I managed to slide the view upwards. However I want to dismiss the keyboard and the view comes down and fits the screen .I tried using tap gesture and click on return button but nothing seems to work. How do I do make the view slide down and keyboard disappear?
Moreover how can i change the width of text field so that multiple lines can appear when the user is writing the message?
you can add tap gesture event to tableview cell and also you can use touch event method when user click on tableview then according to keyboard previous state you can display or hide keyboard. Hope this will help to u.
Use textFieldShouldReturn to resign first responder status (dismiss the keyboard) and slide the view up.
Personally I do it this way:
I register for notifications to know when the keyboard will be shown, and when it will be hidden.
When the keyboard appears, I set the view insets to include the size of the keyboard.
Slide the view up
When the keyboard will disappear, I set the insets to zero.
TextField Delegate Method to hide the keyboard when the Return button is tapped
-(BOOL)textFieldShouldReturn:(UITextField*)textField;
{
[textField resignFirstResponder];
return NO; // We do not want the UITextField to insert line-breaks.
}
Register for keyboard appear/disappear notifications
- (void)viewDidLoad
{
...
// Register for notifications for when the keyboard will appear and disappear
[self registerForKeyboardNotifications];
}
// Call this method somewhere in your view controller setup 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.
// Original code for this part here: http://stackoverflow.com/a/16044603/4518324
- (void)keyboardWasShown:(NSNotification *)note
{
NSDictionary *userInfo = note.userInfo;
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
CGRect keyboardFrameEnd = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardFrameEnd = [self.view convertRect:keyboardFrameEnd fromView:nil];
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
self.view.frame = CGRectMake(0, 0, keyboardFrameEnd.size.width, keyboardFrameEnd.origin.y);
} completion:nil];
}
- (void)keyboardWillBeHidden:(NSNotification *)note
{
NSDictionary *userInfo = note.userInfo;
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
CGRect keyboardFrameEnd = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardFrameEnd = [self.view convertRect:keyboardFrameEnd fromView:nil];
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
self.view.frame = CGRectMake(0, 0, keyboardFrameEnd.size.width, keyboardFrameEnd.origin.y);
} completion:nil];
}
I have created sample code that involves resizing the view when they keyboard is shown or dismissed.
https://github.com/gingofthesouth/KeyboardHideShow
I got it right . I had another method called out when keyboard is dismissed which fit the view frame as per requirement which is View.frame-keyboard.frame.height. Thanks anyways!:)
Related
[UIView animateWithDuration:0.6 delay:0.0 options:UIViewAnimationCurveLinear animations:^{
[self.searchField becomeFirstResponder];
} completion:nil];
animates the keyboard entry by having it appear as if its far away and in the top left corner of the screen, swinging inward in a slightly curved line to it's final resting spot.
This happens no matter what UIView animation method I use.
Even stranger, it only happens once. Not just once per view controller, but ONCE, period. Dispatch_once style.
The effect I'm looking for (which works all subsequent times my method is called, and works for [self.view endEditing]) is just a standard linear entry every time. I need this inside an animation block to keep it on the same time schedule as an animation I have that slides down my searchField from under the status bar.
My question - How can I guarantee consistent animation of [viewObject becomeFirstResponder] inside UIView animation blocks?
The reason the keyboard comes from the top left corner the first time you animate it is because it's initial position and size is (0,0,0,0). So on first creation (the first animation block) it animates from (0,0,0,0) to whatever the frame is when it is visible on screen. Subsequent calls to that animation will show the keyboard in the right initial position and then animate properly.
In my research I found someone say it is very bad practice to put Apple built in animations inside your animation blocks, and I agree.
The way to get around this is to listen for keyboard motion, get the properties from the keyboard Apple defined animation and do your animating with the same properties. Something like this from this answer:
Setup your keyboard listening:
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)dealloc {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
And then setup the functions to mimick they keyboard animation properties:
- (void)keyboardWillHide:(NSNotification *)n
{
NSDictionary* userInfo = [n userInfo];
// get the size of the keyboard
CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
// resize the scrollview
CGRect viewFrame = self.scrollView.frame;
// I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
viewFrame.size.height += (keyboardSize.height - kTabBarHeight);
NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration;
[animationDurationValue getValue:&animationDuration];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:animationDuration];
//Your animations go here
[UIView commitAnimations];
keyboardIsShown = NO;
}
You should be able to extract what you need from these bits of code and make your app look exactly like you would like it to. Good luck.
You can use the values for UIKeyboardAnimationCurveUserInfoKey and UIKeyboardAnimationDurationUserInfoKey keys of userInfo property from UIKeyboardWillShowNotification to synchronize your animation with the keyboard animation.
I am a fairly new iPhone developer, and I am working on an iPhone app that has a view where the user needs to enter input into multiple UITextViews. There are a total of 6 UITextViews and when the view appears all the text views are visible without the need to scroll. But when the user clicks on the first text view to enter the text, the last 2 text views become hidden by the keyboard and I can't figure out how to add scrolling capability so the user will be able to scroll when the keyboard is visible. I am using a UIScrollView but currently have no code to make it work since I have tried multiple different things I have found online and none have worked. This may be an easy solution, but I am just out of ideas and have been stuck for a while. Any advice is greatly appreciated. Thanks
More Info: I am using the latest version of Xcode, developing for iPhone versions 6.1 and above. I used the Interface Builder to set up the ScrollView and the AutoLayout box is checked.
in your view did load write following lines
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHide) name:UIKeyboardWillHideNotification object:nil];
Make following methods.
-(void)keyboardDidHide
{
scrollview.frame = YOUR_ORIGINAL_FRAME;//You should set frame when keyboard is not there
scrollview.contentSize=scrollview.frame.size;
}
-(void)keyboardDidShow
{
CGRect r = scrollview.frame;
scrollview.contentSize=scrollview.frame.size;
r.size.height - = 216;//216 is keyboard height for iPhone.
scrollview.frame = r;
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
/* this returns the keyboard when user click on return button which is reside on keyboard */
if([text isEqualToString:#"\n"])
{
[textView resignFirstResponder];
[yourscrollview setContentOffset:CGPointMake(0,0)animated:YES];
}
return YES;
}
-(void)textViewDidEndEditing:(UITextView *)textView
{
/* it used for hide keyboard and set all control on their original position */
}
-(void)textViewDidBeginEditing:(UITextView *)textView
{
/* depending upon condition it will scroll the textview so textview can't reside behind the keyboard */
[yourscrollview setContentOffset:CGPointMake(0,textView.center.y-80)animated:YES];
}
above 80 i was defined because my requirement is to take textview that much up when keyboard appears you can put a value which is suitable to your requirements
Follow 2 simple steps as following
From storyboard/xib, adjust the frame for your scrollview and keep
height as screen size.
Within your viewcontroller apply the contentsize for your view like,
<scrollview>.contentSize=CGSizeMake(320, 700);
You will be able to see your entire scrollview on scrolling.
Use following link to move textview or textfield up and down automatically when keyboard appears
https://github.com/michaeltyson/TPKeyboardAvoiding
this link contains demo project. you can use this as you requirement
i hope this will help you.
You could do it this way:
// In View First add keyboard appearance and disappearance Notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide) name:UIKeyboardWillHideNotification object:nil];
// Now inside this selector method
-(void)keyboardWillShow:(NSNotification *)notify
{
if (!notify) {
return;
}
NSDictionary *userInfo = [notify userInfo];
NSValue *keyboardEndFrame = ([userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]);
CGRect endFrame = keyboardEndFrame.CGRectValue;
// Change the frame of the view to its parent
CGRect loginViewFrame = [loginView.superview convertRect:loginView.frame fromView:loginView];
// Check the keyboard covers the view
if (CGRectGetMinY(endFrame) < CGRectGetMaxY(loginViewFrame))
{
// If YES calculate Distance. Save this difference to animate back the view
difference = CGRectGetMaxY(loginViewFrame)- CGRectGetMinY(endFrame);
// animate that View
[self animateViewUp:YES withMovementDistance:difference];
}
}
// inside Will Hide
-(void)keyboardWillHide
{
// Animate back the view with the calculated distance
[self animateViewUp:NO withMovementDistance:difference];
}
- (void)animateViewUp:(BOOL)up withMovementDistance:(int)movementDistance
{
const float movementDuration = 0.3f;
int movement = (up ? -movementDistance : movementDistance);
[UIView animateWithDuration:movementDuration animations:^{
loginView.frame = CGRectOffset(loginView.frame, 0, movement);
}];
}
I have two UIViews and UIView2 got UITextView which can be placed wherever user likes to add Text label. And when user places UiTextView in the bottom, keyboard appears to type text and UITextView moves up. And it works great! I need also move UIView1 which is under the UIView1.
UIView2 is property of UIView1 and i need Notify UIView1 to do Move Up methods for it when UITextView of UIView2 becomeFirstResponder.
[[NSNotificationCenter defaultCenter] addObserver:self.drawingView
selector:#selector(keyboardWillShow)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self.drawingView
selector:#selector(keyboardWillHide)
name:UIKeyboardWillHideNotification
object:nil];
You've add notification for keyboard Events then what you have to do is to implement the method keyboardWillShow and keyboardWillHide. See below
- (void)keyboardWillShow:(NSNotification *)notification {
/*
Reduce the size of the text view so that it's not obscured by the keyboard.
Animate the resize so that it's in sync with the appearance of the keyboard.
*/
NSDictionary *userInfo = [notification userInfo];
// Get the origin of the keyboard when it's displayed.
NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
// Get the top of the keyboard as the y coordinate of its origin in self's view's coordinate system. The bottom of the text view's frame should align with the top of the keyboard's final position.
CGRect keyboardRect = [aValue CGRectValue];
// Get the duration of the animation.
NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration;
[animationDurationValue getValue:&animationDuration];
// Animate the resize of the text view's frame in sync with the keyboard's appearance.
[self moveCommentBarViewWithKeyBoardHeight:keyboardRect.size.height withDuration:animationDuration];
}
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary* userInfo = [notification userInfo];
/*
Restore the size of the text view (fill self's view).
Animate the resize so that it's in sync with the disappearance of the keyboard.
*/
NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration;
[animationDurationValue getValue:&animationDuration];
[self moveCommentBarViewWithKeyBoardHeight:0 withDuration:animationDuration];
}
hope it could hlep:)
PS: when add this notification, you better add to method -(void)viewWillAppear:(BOOL)animite. And use
[[NSNotificationCenter defaultCenter] removeObserver:self];
to removew observe when viewWillDisappear.
-(void)moveCommentBarViewWithKeyBoardHeight:(CGFloat)kHeighy withDuration:(NSTimeInterval)animationD
{
CGRect tempRect = commentEditedBarView.frame;
[UIView beginAnimations:#"Animation" context:nil];
[UIView setAnimationDuration:animationD];
[commentEditedBarView setFrame:CGRectMake(tempRect.origin.x, self.view.frame.size.height-kHeighy-tempRect.size.height, tempRect.size.width, tempRect.size.height)];
[UIView commitAnimations];
}
I have an instance of UIToolbar that contains a UITextField inside. I'd like to set the toolbar at an accessory view for the UITextField it contains.
The way I do this is as follows:
[myTextView setInputAccessoryView:myToolbar];
When I compile and run the code, the entire keyboard disappears when I press on the text field. I specifically made sure I am setting the inputAccessoryView and not the inputView. It seems like the whole input view just got replaced, without any explicit direction to do so.
Does anyone know a way to fix this?
It's generally not good to put a text field in an input accessory view... What would be better is if you put the toolbar along the bottom of your view and then use UIKeyboardWillChangeFrameNotification to move the toolbar with the keyboard...
In your viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
And somewhere in your view controller's code:
-(void) keyboardWillChange:(NSNotification*)notify {
CGRect endFrame;
float duration = [[[notify userInfo] valueForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
[[[notify userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&endFrame];
endFrame = [self.view convertRect:endFrame fromView:nil];
float y = (endFrame.origin.y > self.view.bounds.size.height ? self.view.bounds.size.height-44 : endFrame.origin.y-44);
[UIView animateWithDuration:duration animations:^{
toolbar.frame = CGRectMake(0, y, self.view.bounds.size.width, 44);
}];
}
I have a view-based application, and in one of the subviews there is a UIScrollView. I have written handlers to adjust the size of the scroll view when the keyboard appears and disappears. I would like the keyboard to be dismissed when the user leaves the view, so I call [currentField resignFirstResponder] in viewWillDisappear. This dismisses the keyboard, but does not call the handler to resize the scroll view (when I call the same code in other places, it does). Any suggestions?
EDIT: These are the handlers that I use:
-(void) keyboardWasShown:(NSNotification*) notification
{
if(keyboardShown)
return;
NSDictionary* info=[notification userInfo];
NSValue* value=[info objectForKey:UIKeyboardFrameEndUserInfoKey];
CGSize keyboardSize=[value CGRectValue].size;
CGRect viewFrame=[scrollView frame];
viewFrame.size.height-=keyboardSize.height;
scrollView.frame=viewFrame;
keyboardShown=YES;
}
-(void) keyboardWasHidden:(NSNotification*) notification
{
NSDictionary* info=[notification userInfo];
NSValue* value=[info objectForKey:UIKeyboardFrameEndUserInfoKey];
CGSize keyboardSize=[value CGRectValue].size;
CGRect viewFrame=[scrollView frame];
viewFrame.size.height+=keyboardSize.height;
scrollView.frame=viewFrame;
keyboardShown=NO;
}
When I call [currentField resignFirstResponder] anywhere else, it calls the handler without problems.
So you were being removed as observer before UIKeyboardDidHideNotification was posted, glad I could help. But observing the UIKeyboardWillHideNotification and UIKeyboardWillShowNotification is probably enough for your reaction to the keyboard. The keyboard notifications have a user info key UIKeyboardAnimationDurationUserInfoKey which you can use to animate your frame adjustments with the keyboard animations. This avoids the 'clunk' feeling your views will have if you don't animate them to new positions. Here is a quick example of what you can do:
-(void)keyboardWillNotificationTarget:(NSNotification *)note{
// Find current keyboard origin Y
NSValue *keyboardCurrentFrameValue = [note.userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey];
CGFloat currentOriginY = keyboardCurrentFrameValue.CGRectValue.origin.y;
// Find keyboard Y that will be
NSValue *keyboardNewFrameValue = [note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGFloat newOriginY = keyboardNewFrameValue.CGRectValue.origin.y;
// Calculate new frame for scrollView
CGFloat heightChangeForScrollView = newOriginY - currentOriginY;
CGRect svFrame = scrollView.frame;
svFrame.size.height += heightChangeForScrollView;
// Find duration of animation
NSNumber *animationDurationNumber = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
CGFloat animationDuration = animationDurationNumber.floatValue;
// Animate scrollView with keyboard
[UIView animateWithDuration:animationDuration animations:^{
scrollView.frame = svFrame;
}];
}
Now you simply add this method as the target for both notifications:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillNotificationTarget:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillNotificationTarget:) name:UIKeyboardWillHideNotification object:nil];