简体   繁体   English

为UITextField设置动画时的奇怪行为

[英]Strange behavior when animating UITextField

I'm trying to animate a UITextField but I've been caught by a annoying and strange problem. 我正在尝试为UITextField设置动画,但是我却被一个烦人而又奇怪的问题所困扰。 My animation has the following sequence: 我的动画具有以下顺序:

第一状态

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. 在第一种状态下,应用程序在未显示的摄像头按钮之后具有UITextField ,摄像头UIButton和取消UIButton ,因为其位置超出了应用程序的限制。 Actually my application has 320 of width and the cancel button origin is (350,7) 实际上,我的应用程序的宽度为320,取消按钮的原点为(350,7)

第二状态

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). 在第二种状态下,当用户触摸UITextField ,相机按钮的alpha通道设置为0,取消按钮的原点设置为(247,7)。

最终状态

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. 在处理期间,将对UITextField宽度和x轴上的“取消”按钮原点进行动画处理。

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. 当动画第一次执行直到直到最终状态时,这意味着用户触摸了UITextField,WROTE DOWN(此部分很重要)在字段上显示了一些文本,然后用户触摸了键盘返回按钮,便出现了问题。 The problem is that the typed text in UITextField is animated when the width of UITextField is animated too. 问题在于,当UITextField的宽度也被动画化时,UITextField中的键入文本也会被动画化。

The animation behaves like bellow: 动画的行为像下面这样:

  1. The UITextField stretches back to its initial value. UITextField延伸回其初始值。
  2. Cancel button backs to its initial origin 取消按钮返回到其初始位置
  3. Camera button is set to 1.0 相机按钮设置为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. 键入的文本从UITextField左上角飞过,并落入UITextfield到达的位置。

The problem is that the step 4 should not happen and the problem is it happens only one time. 问题是步骤4不应该发生,而问题是它只发生一次。 If a start the process again (touch on uitextfield, type some text, touch on return key) the step 4 does not happen. 如果再次开始该过程(触摸uitextfield,键入一些文本,触摸返回键),则不会发生步骤4。

I spend a day long trying to solve this problem but I was unsuccessful. 我花了整整一天的时间来尝试解决此问题,但未成功。

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 . 根据键盘状态,在UITextField启动动画的正确方法是重写textFieldShouldBeginEditingtextFieldShouldEndEditing方法。

My first attempt I was overriding textFieldDidBeginEditing and textFieldDidEndEditing to create the animations. 我的第一次尝试是重写textFieldDidBeginEditingtextFieldDidEndEditing来创建动画。 I don't know the reason to the animations work in textFieldShouldBeginEditing and textFieldShouldEndEditing but not in textFieldDidBeginEditing and textFieldDidEndEditing . 我不知道原因在动画工作textFieldShouldBeginEditingtextFieldShouldEndEditing但不是在textFieldDidBeginEditingtextFieldDidEndEditing 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;
}

Set some placeholder text on the search field, _searchField.text = @"placeholder" 在搜索字段_searchField.text = @“ placeholder”上设置一些占位符文本

and also set _searchField.clearsOnBeginEditing = YES; 并设置_searchField.clearsOnBeginEditing = YES;

Or you can just clear out the value if it's equal to your placeholder text on textDidBeginEditing 或者,您可以清除值是否等于textDidBeginEditing上的占位符文本

{edited to improve the fix} I have this exact same problem, and some further details as well as a small hack that is indeed fixing it for me. {编辑以改进此修复程序}我也有同样的问题,还有更多详细信息以及确实为我修复了一个小技巧。

So first the further details: 所以首先是更多细节:

  1. The problem only occurs the first time the frame animation expands the UITextField and there is entered text in the field. 仅在框架动画第一次扩展UITextField并在字段中输入文本时才会出现此问题。 If the UITextField is edited again, and the same animations happen again, the problem does not happen. 如果再次编辑UITextField ,并且再次发生相同的动画,则不会发生此问题。
  2. searchField.clearsOnBeginEditing = YES; does not clear the problem. 不能解决问题。
  3. I've been using placeholder text the entire time the problem has been observed. 在观察到问题的整个过程中,我一直在使用占位符文本。 It has no effect on the results. 它对结果没有影响。
  4. Changing the text property for 1 frame does have the effect of clearing the problem. 更改一帧的text属性确实可以解决问题。

Here is what I am doing to fix it: 这是我正在解决的问题:

In my viewDidLoad I am setting the text property to a single space, then dispatching once an assignment to an empty string. 在我的viewDidLoad我将text属性设置为一个空格,然后将一次分配分配给一个空字符串。

-(void)viewDidLoad {
    searchField.text = @" ";
    dispatch_async(dispatch_get_main_queue(), ^{
        searchField.text = @"";
    });
}

Then in my methods that shrink and expand the UITextField , as well as move a cancel button on-screen, I check if this is an instantaneous animation and set the duration to 0.0f. 然后,在缩小和扩展UITextField方法以及在屏幕上移动取消按钮的方法中,我检查这是否是瞬时动画,并将持续时间设置为0.0f。

- (void)showCancelButton {
    NSTimeInterval duration = 0.3f;

    [UIView animateWithDuration:duration animations:^{ 
        CGPoint buttonOrigin = cancelButton.frame.origin;
        CGSize buttonSize = cancelButton.frame.size;
        CGFloat buttonTravelDist = buttonSize.width + 10.0f;
        CGPoint onscreenPos = CGPointMake(buttonOrigin.x - buttonTravelDist, buttonOrigin.y);

        cancelButton.frame = CGRectMake(onscreenPos.x, onscreenPos.y, buttonSize.width, buttonSize.height);

        CGPoint fieldOrigin = searchField.frame.origin;
        CGSize fieldSize = searchField.frame.size;

        searchField.frame = CGRectMake(fieldOrigin.x, fieldOrigin.y, fieldSize.width - buttonTravelDist, fieldSize.height);
    }];
}

- (void)hideCancelButton {
    NSTimeInterval duration = 0.3f;

    [UIView animateWithDuration:duration animations:^{ 
        CGPoint buttonOrigin = cancelButton.frame.origin;
        CGSize buttonSize = cancelButton.frame.size;
        CGFloat buttonTravelDist = buttonSize.width + 10.0f;
        CGPoint onscreenPos = CGPointMake(buttonOrigin.x + buttonTravelDist, buttonOrigin.y);

        cancelButton.frame = CGRectMake(onscreenPos.x, onscreenPos.y, buttonSize.width, buttonSize.height);

        CGPoint fieldOrigin = searchField.frame.origin;
        CGSize fieldSize = searchField.frame.size;

        searchField.frame = CGRectMake(fieldOrigin.x, fieldOrigin.y, fieldSize.width + buttonTravelDist, fieldSize.height);
    }];
}

This has completely fixed the situation for me. 这完全为我解决了这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM