Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior when animating UITextField

I'm trying to animate a UITextField but I've been caught by a annoying and strange problem. My animation has the following sequence:

first state

In first state the application has the UITextField, the camera UIButton and the cancel UIButton after the camera button that is not been showed because it is been positioned out of the limits of the application. Actually my application has 320 of width and the cancel button origin is (350,7)

second state

In second state, when user touches on UITextField, the camera button alpha channel is set to 0 and the origin of cancel button is set to (247,7).

final state

The final state is the same as first state after user touched on Return button of keyboard or in cancel button.

During process the UITextField width and the cancel button origin in x axis are animated.

My code is:

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
  barcodeSearchButton.userInteractionEnabled = NO;
  cancelButton.userInteractionEnabled = NO;

   CGFloat cancelButtonXOffset = CGRectGetMaxX(barcodeSearchButton.frame) - cancelButton.frame.size.width;
   CGFloat searchFieldWidth = searchField.frame.size.width - cancelButton.frame.size.width + barcodeSearchButton.frame.size.width;
   [UIView animateWithDuration:0.3
         animations:^{
             searchField.frame = CGRectMake(searchField.frame.origin.x, searchField.frame.origin.y, searchFieldWidth, searchField.frame.size.height);
             cancelButton.alpha = 1.0;                
             cancelButton.frame = CGRectMake(cancelButtonXOffset, cancelButton.frame.origin.y, cancelButton.frame.size.width,cancelButton.frame.size.height);

             barcodeSearchButton.alpha = 0.0;

         }
         completion:^(BOOL finished) {
             barcodeSearchButton.userInteractionEnabled = NO;
             cancelButton.userInteractionEnabled = YES;
         }];    
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
  barcodeSearchButton.userInteractionEnabled = NO;
  cancelButton.userInteractionEnabled = NO;

  [UIView animateWithDuration:0.3
                 animations:^{
                     searchField.frame = CGRectMake(searchField.frame.origin.x, searchField.frame.origin.y, searchFieldStartWidth, searchField.frame.size.height);
                     cancelButton.alpha = 0.0;
                     cancelButton.frame = CGRectMake(cancelButtonStartX, cancelButton.frame.origin.y, cancelButton.frame.size.width,cancelButton.frame.size.height);
                     barcodeSearchButton.alpha = 1.0;                
                 }
                 completion:^(BOOL finished) {
                     barcodeSearchButton.userInteractionEnabled = YES;
                     cancelButton.userInteractionEnabled = NO;
                 }];        
}

When the animation is executed until the final state ONLY for the first time, which means, user touched on UITextField, WROTE DOWN (this part is important) some text on field and after that the user touched on keyboard return button the problem appears. The problem is that the typed text in UITextField is animated when the width of UITextField is animated too.

The animation behaves like bellow:

  1. The UITextField stretches back to its initial value.
  2. Cancel button backs to its initial origin
  3. Camera button is set to 1.0
  4. The typed text flies from the top-left corner of UITextField and it lands into UITextfield to the position the it should not have gone.

The problem is that the step 4 should not happen and the problem is it happens only one time. If a start the process again (touch on uitextfield, type some text, touch on return key) the step 4 does not happen.

I spend a day long trying to solve this problem but I was unsuccessful.

like image 952
Fabio Avatar asked Nov 10 '11 22:11

Fabio


1 Answers

Thanks for answers of everyone but I've found the solution some time ago. The correct way to start an animation in a UITextField, depending on the keyboard state, is overriding the methods textFieldShouldBeginEditing and textFieldShouldEndEditing.

My first attempt I was overriding textFieldDidBeginEditing and textFieldDidEndEditing to create the animations. I don't know the reason to the animations work in textFieldShouldBeginEditing and textFieldShouldEndEditing but not in textFieldDidBeginEditing and textFieldDidEndEditing. But it just works.

My revised code version:

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {

    CGFloat cancelButtonXOffset = CGRectGetMaxX(barcodeSearchButton.frame) -    cancelButton.frame.size.width;
    CGFloat searchFieldWidth = searchField.frame.size.width - cancelButton.frame.size.width + barcodeSearchButton.frame.size.width;
    [UIView animateWithDuration:0.3
         animations:^{
             searchField.frame = CGRectMake(searchField.frame.origin.x, searchField.frame.origin.y, searchFieldWidth, searchField.frame.size.height);
             cancelButton.alpha = 1.0;                
             cancelButton.frame = CGRectMake(cancelButtonXOffset, cancelButton.frame.origin.y, cancelButton.frame.size.width,cancelButton.frame.size.height);

             barcodeSearchButton.alpha = 0.0;

         } completion:^(BOOL finished) {
             searchField.clearButtonMode = UITextFieldViewModeAlways;
         }]; 
    return YES;
}

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    [UIView animateWithDuration:0.3
         animations:^{
             searchField.frame = CGRectMake(searchField.frame.origin.x, searchField.frame.origin.y, searchFieldStartWidth, searchField.frame.size.height);
             cancelButton.alpha = 0.0;
             cancelButton.frame = CGRectMake(cancelButtonStartX, cancelButton.frame.origin.y, cancelButton.frame.size.width,cancelButton.frame.size.height);
             barcodeSearchButton.alpha = 1.0;                
         } completion:^(BOOL finished) {
             searchField.clearButtonMode = UITextFieldViewModeNever;
         }];
   return YES;
}
like image 168
Fabio Avatar answered Oct 15 '22 09:10

Fabio