My UIView is not moving up when keyboard shown and disappear when keyboard is hidden as well.
This coding is in ViewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
and this coding is for the rest.
- (void)keyboardDidShow:(NSNotification *)note
{
[self animateTextField:TRUE];
}
- (void)keyboardDidHide:(NSNotification *)note
{
[self animateTextField:FALSE];
}
-(void)animateTextField :(BOOL)up
{
const int movementDistance = -130; // tweak as needed
const float movementDuration = 1.0; // tweak as needed
int movement = (up ? movementDistance : - movementDistance);
[UIView beginAnimations: #"animateTextField" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
_buttonsView.frame = CGRectOffset(_buttonsView.frame, 0, movement);
[UIView commitAnimations];
}
I think this suits your implementation:
-(void)animateTextField :(BOOL)up
{
const int movementDistance = -130; // tweak as needed
const float movementDuration = 1.0; // tweak as needed
int movement = (moveUp ? movementDistance : - movementDistance);
[UIView beginAnimations: #"animateTextField" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
_buttonsView.frame = CGRectOffset(_buttonsView.frame, 0, movement);
[UIView commitAnimations];
[_buttonsView setNeedsLayout];
}
Edit
I tried your code and calling setNeedsLayout did the work..
With auto-layout you animate the constraint constant, though you don't change the CGRect frames. That was the old way.
Please see this link that I answered a similar question that they were having issues animating the movement of a UIView
Animate UIView with layoutConstraints
This should help, though feel free to let me know if you need anything clarified.
use just below code you don't need to call it from any where
#pragma mark - move view up when keyboard is displayed
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField: textField up: YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField: textField up: NO];
}
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
contentView.frame = CGRectOffset( contentView.frame, 0, movement);
[UIView commitAnimations];
}
Related
I'm using the below code to shift a view and my tableview up when my keyboard is activated. When the keyboard is closed however, it takes the upView a solid 2 seconds after the keyboard closes to return to where it was (the tableView on the other hand, is instant). Why is this happening?
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillChange:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)keyboardWillChange:(NSNotification *)notification {
NSDictionary* keyboardInfo = [notification userInfo];
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
UITabBarController *tabBarController = [UITabBarController new];
CGFloat tabBarHeight = tabBarController.tabBar.frame.size.height;
self.keyboardHeight = keyboardFrameBeginRect.size.height - tabBarHeight;
}
- (void) animateTextView:(BOOL) up
{
const int movementDistance = self.keyboardHeight;
const float movementDuration = 0.2f;
int movement= movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.upView.frame = CGRectOffset(self.upView.frame, 0, movement);
[UIView setAnimationDidStopSelector:#selector(afterAnimationStops)];
[UIView commitAnimations];
self.tableView.frame = CGRectOffset(self.tableView.frame, 0, movement);
[UIView setAnimationDidStopSelector:#selector(afterAnimationStops)];
[UIView commitAnimations];
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
[self animateTextView:YES];
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
[self animateTextView:NO];
}
UPDATED CODE
.m
- (void)handleKeyboard:(NSNotification*)aNotification{
NSDictionary* info = [aNotification userInfo];
NSValue* value = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval duration = 3;
[value getValue:&duration];
if (aNotification.name == UIKeyboardWillHideNotification) {
/** KEYBOARD HIDE **/
[UIView animateWithDuration:0 animations:^{ self.upView.frame = CGRectOffset(self.upView.frame, 0, self.keyboardHeight); self.tableView.frame = CGRectOffset(self.tableView.frame, 0, self.keyboardHeight); } completion:^(BOOL finished) {}];
[self moveCustomView:NO duration:duration];
NSLog(#"CLOSED!");
}
if (aNotification.name == UIKeyboardWillShowNotification) {
/** KEYBOARD SHOW **/
[UIView animateWithDuration:0 animations:^{ self.upView.frame = CGRectOffset(self.upView.frame, 0, -self.keyboardHeight); self.tableView.frame = CGRectOffset(self.tableView.frame, 0, -self.keyboardHeight); } completion:^(BOOL finished) {}];
[self moveCustomView:YES duration:duration];
}
}
- (void)moveCustomView:(BOOL)move duration:(NSTimeInterval)time{
}
This issue might be with the animation duration, so you can get the keyboard showing and hiding animation duration from the -(void)handleKeyboard:(NSNotification *)notification {}
and also handle the showing and hiding your custom view inside the same function. Add the following code to your viewDidLoad function
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleKeyboard:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleKeyboard:) name:UIKeyboardWillShowNotification object:nil];
Handle keyboard actions and UI changes
- (void)handleKeyboard:(NSNotification*)aNotification{
NSDictionary* info = [aNotification userInfo];
NSValue* value = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval duration = 0;
[value getValue:&duration];
if (aNotification.name == UIKeyboardWillHideNotification) {
/** KEYBOARD HIDE **/
//calculate your view frames and handle UI changes
/*
.
.
.
.
.
*/
[self moveCustomView:NO duration:duration];
}
if (aNotification.name == UIKeyboardWillShowNotification) {
/** KEYBOARD SHOW **/
//calculate your view frames and handle UI changes
/*
.
.
.
.
.
*/
[self moveCustomView:YES duration:duration];
}
}
- (void)moveCustomView:(BOOL)move duration:(NSTimeInterval)time{
}
I think you need to use thread to call animation immediately...
- (void)textViewDidBeginEditing:(UITextView *)textView {
dispatch_async(dispatch_get_main_queue(), ^{
[self animateTextView:YES];
});
}
- (void)textViewDidEndEditing:(UITextView *)textView {
dispatch_async(dispatch_get_main_queue(), ^{
[self animateTextView:NO];
});
}
I'm not much aware of your problem, but try this because if we got this type of problems dispatch_async() will solve.
This is so strange - for some reason, when my UIView animates up
(once I tap my UITextView), my UITapGesture doesn't execute? E.g. tapping anywhere on the view once the view is animated and UITextView is active doesn't dismiss the animated view? However if I tap anywhere on the view BEFORE it animates, UITapGesture executes just fine - why is this?
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.replyField.delegate = self;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
}
-(void)dismissKeyboard {
[self animateTextView:NO];
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
[self animateTextView: YES];
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
[self animateTextView:NO];
}
- (void) animateTextView:(BOOL) up
{
const int movementDistance = 206; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement= movement = (up ? -movementDistance : movementDistance);
NSLog(#"%d",movement);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.inputView.frame, 0, movement);
[UIView commitAnimations];
}
Once try like,
- (void) animateTextView:(BOOL) up
{
UIViewAnimationOptions options = UIViewAnimationOptionAllowUserInteraction;
const int movementDistance = 206; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement= movement = (up ? -movementDistance : movementDistance);
[UIView animateWithDuration:movementDuration
delay:0.0
options:options
animations:^{
self.view.frame = CGRectOffset(self.inputView.frame, 0, movement);
}
completion:nil];
}
I've made it so that when a user taps on a text field, the view shifts up slightly so that the fields are still visible while a user is typing. It works great, however sometimes after the keyboard is dismissed, instead of returning to its original position, the view slides down too far (leaving a small blank black bar at the top). Does anyone know how I can just restore the view back to its original position? Here's my code:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_userField.returnKeyType = UIReturnKeyDone;
[_userField setDelegate:self];
_passField.returnKeyType = UIReturnKeyDone;
[_passField setDelegate:self];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
}
- (void)dismissKeyboard
{
[_userField resignFirstResponder];
[_passField resignFirstResponder];
}
-(void)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
}
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField:textField up:YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField:textField up:NO];
}
-(void)animateTextField:(UITextField*)textField up:(BOOL)up
{
const int movementDistance = -130; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? movementDistance : -movementDistance);
[UIView beginAnimations: #"animateTextField" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
I would suggest you to work with the keyboard notifications instead. That way, it would work even if you have more than one field, you will be able to animate the change along with the keyboard animation, and you will know exactly how much screen estate you are loosing due to the keyboard showing.
First, in your view controller, register and unregister for the notifications:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShowNotification:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHideNotification:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
Then implements the two methods being called when the notifications are triggered:
- (void)keyboardWillShowNotification:(NSNotification *)notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:(UIViewAnimationCurve)[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
[UIView setAnimationBeginsFromCurrentState:YES];
CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
[self.mainView adjustContentWithKeyboardHeight:keyboardFrame.size.height];
[UIView commitAnimations];
}
- (void)keyboardWillHideNotification:(NSNotification *)notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:(UIViewAnimationCurve)[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
[UIView setAnimationBeginsFromCurrentState:YES];
[self.mainView adjustContentWithKeyboardHeight:0];
[UIView commitAnimations];
}
Finally, implement a adjustContentWithKeyboardHeight public method in your view. Since that method is called in a UIView animation, all the changes will be animated.
If you are moving the views directly (put them all in a container view that you will move), keep the original Y position in a private property, then subtract from that property the keyboardHeight minus the remaining space below your textField, and assign that back to that field (or set the frame to your liking):
CGFloat offsetY = keyboardHeight - (CGRectGetHeight(self.bounds) - CGRectGetMaxY(self.containerView.frame));
CGRect containerFrame = self.containerView.frame;
containerFrame.origin.y = self.containerViewPositionY - offsetY;
self.containerView.frame = containerFrame;
I have set a UITextView on full screen of device like in iphone-5s,textView size is (0,44,320,524). when keyboard appear then user cant show the insert text in view.how can I manage the UITextView, can i use UIScrollView for it or any thing else?
While editing complete View will move up and after done editing will move down...
(void)textViewDidBeginEditing:(UITextView *)textView {
[self animateTextView: YES];
}
(void)textViewDidEndEditing:(UITextView *)textView {
[self animateTextView:NO];
}
(void) animateTextView:(BOOL) up {
const int movementDistance =heightKeyboard; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement= movement = (up ? -movementDistance : movementDistance);
NSLog(#"%d",movement);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.inputView.frame, 0, movement);
[UIView commitAnimations];
}
I hope it will work for you.
I have solved it by using this code
.h file define a value
CGRect originalTextViewFrame;
.m file
- (void)viewWillAppear:(BOOL)animated
{
// Register notifications for when the keyboard appears
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardWillShow:(NSNotification*)notification
{
[self moveTextViewForKeyboard:notification up:YES];
}
- (void)keyboardWillHide:(NSNotification*)notification
{
[self moveTextViewForKeyboard:notification up:NO];
}
- (void)moveTextViewForKeyboard:(NSNotification*)notification up:(BOOL)up
{
NSDictionary *userInfo = [notification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardRect;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
keyboardRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
if (up == YES) {
CGFloat keyboardTop = keyboardRect.origin.y;
CGRect newTextViewFrame = textView.frame;
originalTextViewFrame = textView.frame;
newTextViewFrame.size.height = keyboardTop - textView.frame.origin.y - 10;
textView.frame = newTextViewFrame;
}
else
{
// Keyboard is going away (down) - restore original frame
textView.frame = originalTextViewFrame;
}
[UIView commitAnimations];
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
// Any new character added is passed in as the "text" parameter
if ([text isEqualToString:#"\n"])
{
// Be sure to test for equality using the "isEqualToString" message
[textView resignFirstResponder];
//[scrlView setContentOffset:CGPointMake(0,0) animated:YES];
// Return FALSE so that the final '\n' character doesn't get added
return FALSE;
}
// For any other character return TRUE so that the text gets added to the view
return TRUE;
}
use scroll view and then after try
UITextViewDelegate
method
- (void)textViewDidBeginEditing:(UITextView *)textView
{
[scrollView setContentOffset:CGPointMake(0,yourtextview.center.y-200) animated:YES];
}
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.