Im dynamically creating textFields on UIScrollView, I'm animating View to bring textField above the keyboard if keyboard is hiding it. To animate View is used code given below:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect textFiledFrame = textField.frame;
if (textFiledFrame.origin.y > 219 && textField.tag > 150 && viewAnimated == 0) {
CGRect superViewFrame = textField.superview.frame;
superViewFrame.origin.y = superViewFrame.origin.y - 120;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.6];
[textField.superview setFrame:superViewFrame];
[UIView commitAnimations];
viewAnimated = 1;
}
}
for every single time i'm clicking on textFields textFieldDidBeginEditing:(UITextField *)textField is being call but once view get animated, textFieldDidBeginEditing:(UITextField *)textField is not being called
There are several things wrong with your code:
You should not hardcode any keyboard related sizes. Instead make use of the keyboard information the iOS framework provides you (see e.g. here: How to make a UITextField move up when keyboard is present?)
You do set ViewAnimated = 1 in your if statement - do you ever rest it to 0? If not, the if statement will never be entered again, as you check on ViewAnimated == 0 in the if clause ...
Variables should not start with a capital letter (Rect, ViewAnimated) - better is textRect en viewAnimated
Related
I have a UITextView that animates its frame when the keyboard appears like so:
- (void)keyboardWasShown:(NSNotification*)n {
double duration = [[[n userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration:duration
delay:0.3
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CGRect tfFrame = self.tf.frame;
tfFrame.origin.y = tfFrame.origin.y - kbSize.height + 86.f;
[self.tf setFrame:tfFrame];
}
completion:nil
];
}
There is another UITextField directly below this text field which also animates into place when the keyboard appears. After animation, when the keyboard appears, and I touch the second text field, all of the animations revert back into their original positions.
I've logged the frame's y value through each of the UITextField delegate methods to try to pinpoint where the field is changing, and it seems to change when the first field resigns first responder:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
NSLog(#"did begin: %f", self.tf.frame.origin.y);
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
NSLog(#"did end: %f", self.tf.frame.origin.y);
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
NSLog(#"should end: %f", self.tf.frame.origin.y);
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSLog(#"should return: %f", self.tf.frame.origin.y);
return YES;
}
From the console:
2015-03-27 did begin: 521.000000
2015-03-27 should end: 90.294118
2015-03-27 did end: 521.000000
So far I have:
Tried to modify the autolayout constrains when I adjust the frame
Tried to completely remove the autolayout constraints
Unfortunately, I don't know where to go from here. I believe this to be an issue with either first responder status on the text fields or autolayout. What should I start checking?
In my app I've this login screen:
Above the first test field I've an image, the configuration in Interface Builder is the follow:
Now when I tap on the UITextField they should move up otherwise in iPhone 4/4s the field will be covered by keyboard.
Now I'm using the following code:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frameView = self.view.frame;
CGRect frameImage = self.imageViewLogo.frame;
CGRect frameTextFieldUsername = self.textFieldUsername.frame;
CGRect frameTextFieldPassword = self.textFieldPassword.frame;
CGRect frameButtonLogin = self.buttonLogin.frame;
frameView.origin.y = -100;
frameImage.origin.y = -100;
frameTextFieldUsername.origin.y = -100;
frameTextFieldPassword.origin.y = -100;
frameButtonLogin.origin.y = -100;
[self.view setFrame:frameView];
[self.imageViewLogo setFrame:frameImage];
[self.textFieldUsername setFrame:frameTextFieldUsername];
[self.textFieldPassword setFrame:frameTextFieldPassword];
[self.buttonLogin setFrame:frameButtonLogin];
[UIView commitAnimations];
}
When I try to run the app in simulator or on a real device the view scrolls up of 100 but the image, the text fields and button doesn't scrolls up... I thought that the problem depend on the constraints, can you help me to fix this issue?
Thank you
The way in which you are trying to do this will get you in trouble. As you are giving hardcoded values of frame.
Try to use keyboard avoiding library it's the better and safer way of doing it.
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frameView = self.view.frame;
CGRect frameImage = self.imageViewLogo.frame;
CGRect frameTextFieldUsername = self.textFieldUsername.frame;
CGRect frameTextFieldPassword = self.textFieldPassword.frame;
CGRect frameButtonLogin = self.buttonLogin.frame;
frameView.origin.y = -100;
// no need of changing frames of TextFields inside the View, Just change the y-padding of View
[self.view setFrame:frameView];
[UIView commitAnimations];
}
reduce the y-padding to -120 and check
Hope this helps thanks
If your views are set up to use AutoLayout, changing frame will do nothing.
You should subscribe to UIKeyboardWillChangeFrameNotification and perform your changes there. In case of constraints you would update the constrains constants here and the call -setNeedsUpdateConstraints on the superview.
You have to figure out if the keyboards is appearing or disappearing at all if you want to support external keyboard.
Otherwise you can listen for UIKeyboardWillShowNotification and UIKeyboardWillHideNotification
For auto up the textFields while keyboard comes not need to use the thirdParty Classes.
Create a static tableView and design each textFields and button in each static cells.
TableView automatically handle the auto up textFields while keyboard comes.
Hi the simple and easy trick for doing it is :-
Take outlet of top constraint of username or email id textfield in your class and on textfield did begin editing delegate decrease the constraint's constant value so it will goes up when u select the textfield and at textField did end editing delegate again set constraint's constant value to previous one so it will reset on previous position.
eg:-Assuming you set Top Constraint value in Storyboard is 150
-(void)textFieldDidBeginEditing:(UITextField *)textField {
_topConstraint.constant = 10.00;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
_topConstraint.constant = 150.00;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
Hope it will help you.
I have a couple UITextFields that will be hidden by the keyboard when it pops up, so I implemented the UIKeyboardWillShowNotification and UIKeyboardWillHideNotification and sent them to their respective methods:
- (void)keyboardWillShow:(NSNotification*)notification
{
CGFloat height = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
keyBoardHeight = height;
}
- (void)keyboardWillHide:(NSNotification*)notification
{
CGFloat height = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
keyBoardHeight = height;
}
I then have my textfields delegating to this method:
//TextFieldDelegate
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
float keyboardOffset = [self offsetForKeyboard:textField.frame.origin.y withHeight:textField.frame.size.height];
NSLog(#"%f, %f", keyBoardHeight, keyboardOffset);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.1];
self.view.frame = [Global rect:self.view.frame withNewY:-[self offsetForKeyboard:textField.frame.origin.y withHeight:textField.frame.size.height]];
[UIView commitAnimations];
}
The code runs properly, but when I run the code, the keyboardWillShow: method runs after the textFieldDidBeginEditing: method. Because of this, keyboardHeight is set to 0 the first time the code runs, and so the offset I calculate is way off.
How can I make the keyboardWillShow: method run before the textFieldDidBeginEditing: method? Is there another delegate method that I can use instead?
Sorry, but no there's no way to do that. You have to do your animations or whatever you do for keyboard handling inside the notification observer.
Here's what Apple recommends and works fine for me in all cases I've encountered upto now.
Apple's Keyboard Guide
For anyone else who is trying to do this, I found a way:
Maintain a weak reference to the currently editing text field:
UITextField* editingTextField;
- (void)textFieldDidBeginEditing:(UITextField*)textField
{
editingTextField = textField;
}
- (void)textFieldDidEndEditing:(UITextField*)textField
{
editingTextField = nil;
}
Then just reference the weak text field while it is open in the keyboardWillShow: method to calculate the appropriate offsets and move the view accordingly.
- (void)keyboardWillShow:(NSNotification*)notification
{
//Use editingTextField's frame here
}
Simply use IQKeyboardManager. It is a single line code for all textfield in any view.Link: https://github.com/hackiftekhar/IQKeyboardManager
This code was working beautifully in ios 7. However, with ios8 and xcode 6.0.1 it has stopped working. When a user clicked on a text field to enter text, the field animated to float just above the top of the keyboard so they can see what they are typing. Any thoughts on why this fails to work now. I can see it start to animate for a split second, but then the textfield disappears. Frustrating.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.4];
[UIView setAnimationBeginsFromCurrentState:YES];
textField.frame = CGRectMake(textField.frame.origin.x, (textField.frame.origin.y - 200.0),
textField.frame.size.width, textField.frame.size.height);
_searchBtn.frame = CGRectMake(_searchBtn.frame.origin.x, (_searchBtn.frame.origin.y - 200.0),
_searchBtn.frame.size.width, _searchBtn.frame.size.height);
[UIView commitAnimations];
textField.alpha = .75;
}
The problem is that your code adjusts your TextField's position by a fixed value of 200.0
This was probably great for iOS7 but things have changed in iOS8 for two reasons:
The system keyboard has an additional view for showing predicted words while typing
Custom keyboards can be as high as the developer chooses
You need to change your approach move moving the location of your TextField whenever the keyboard is shown or hidden using the following two notifications:
UIKeyboardWillShowNotification
UIKeyboardWillHideNotification
In the following thread I explain the problems that can arise and how to properly move your views around as the keyboard opens:
can't get correct value of keyboard height in iOS8
EDIT 1:
Assuming the textbox has an outlet called "yourTextBox", the code to modify the position of your textbox could look something like:
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
CGFloat keyboardHeight = <<calculated keyboard height as previously discussed>>;
CGFloat textBoxHeight = _yourTextBox.frame.size.height;
// Change the current frame of your textbox in order to reposition it
CGFrame textBoxFrame = _yourTextBox.frame;
textBoxFrame.origin.y = screenHeight - keyboardHeight - textBoxHeight;
_yourTextBox.frame = textBoxFrame;
Note: If you are using AutoLayout constraints to position your subviews you will need to avoid modifying the frame and change your constraints instead. Post if you are having problems in this area because it can get tricky.
I am trying to animate the UISearchBar using the
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
delegate methods, but my implementation of the latter seems to lead to a clumsy animation (slow animation version here). My delegate implementation is shown below (I changed the duration to generate the second video). Is there any way to fix this?
It may be important to note that navigation is a standalone UINavigationBar (I did not use a UINavigationController for this).
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
[UIView animateWithDuration:.25
delay:0.0
options: UIViewAnimationOptionBeginFromCurrentState
animations:^ {
navigation.alpha = 1;
CGRect newTableBounds = chatList.frame;
newTableBounds.size.width -= 40; //newBounds.size.width -= 215; to contract
newTableBounds.origin.x += 40;
newTableBounds.origin.y += 40;
chatList.frame = newTableBounds;
CGRect rootFrame = self.ddParent.rootViewController.view.frame;
rootFrame.origin.x += 40;
self.ddParent.rootViewController.view.frame = rootFrame;
}
completion:nil];
return YES;
}
You aren't adjusting the search bar frame within the animation. The adjustment is taking place immediately, and then the other items are animated. Move it into the animation block, and everything should be good.