当动画UITextField子类的位置时,文本跳动

14
当我对我的UITextField子类的位置进行动画处理时,文本框中的文本会与它所在的UITextField的位置不同步跳动,这非常令人不适,并且我无法弄清楚为什么会发生这种情况: before during during during end

我的子类在文本框的右侧添加了一个按钮,当点击该按钮时,会调用视图控制器上的一个方法,该方法会更改文本框的边框颜色并通过更改文本框的 top space 约束以及其上方的几个其它视图来将文本框向上移动。

[UIView animateWithDuration:0.3
                     animations:^{
                         self.tableViewBottomSpaceConstraint.constant = 0;
                         self.mainLabelHeightConstraint.constant = 0;
                         self.subLabelTopSpaceConstraint.constant = 0;
                         self.postCodeFieldTopSpaceConstraint.constant = 12;
                         [self.view layoutIfNeeded];

                     }];

同样的问题,兄弟。我也遇到了同样的问题。在我的自定义类中,我只是给文本字段左侧添加了一些填充。但还没有找出解决方法。 - Mahesh Agrawal
2
可能是[UITextField中的文本在编辑后向上移动(在编辑时居中)]的重复问题(https://dev59.com/IGkw5IYBdhLWcg3wwNN5)。 - pronebird
3个回答

11

我修复了这个问题。请将您的代码更改为此代码。它会工作。

[UIView animateWithDuration:0.3
                 animations:^{
                     self.tableViewBottomSpaceConstraint.constant = 0;
                     self.mainLabelHeightConstraint.constant = 0;
                     self.subLabelTopSpaceConstraint.constant = 0;
                     self.postCodeFieldTopSpaceConstraint.constant = 12;
                     [self.view layoutSubviews];

                 }];

或者如果这不起作用,那么可以使用

[self.view layoutSubviews];

使用文本字段的父视图和layoutSubviews。在我的情况下,这有效。我认为这个答案有资格获得悬赏。谢谢。

编辑:

我找到了原因。当我们尝试进行layoutIfNeeded时,它意味着首先更改外部布局,然后在更改其布局之后更改UITextField的内部文本,因为我们没有强制更改该文本字段的所有子视图的布局。毕竟,UITextField由UIView、Label和其他基本元素组成。但是,当我们尝试进行layoutSubviews时,它会同时更改所有子视图的布局。这就是为什么弹跳消失了。


1
不要直接调用-layoutSubviews方法,而是调用-layoutIfNeeded方法。 - pronebird
我已经尝试过layoutIfNeeded,但在iOS 8中它没有起作用。我这样做是因为UITextField由几个UIControl组成,其中一个是UILabel,它正在弹跳,如果我们执行layoutIfNeeded,我认为它不会按照所需的方式更改其布局。请在iOS 8中通过添加layoutIfNeeded进行检查。它不起作用,这就是我发布这个问题的原因。但现在在iOS 9中可能会起作用。我不确定。 - Mahesh Agrawal
通常在调用layoutIfNeeded之前,您应该先调用setNeedsLayout来告诉UIKit这个特定的视图需要更新布局。有一定的顺序和内部基础设施来处理更新,并确保它们与旧的“弹簧和支架”以及自动布局正常工作。因为它有效并不是一个解释。如果您有更复杂的UI布局,则可能会导致更多的损坏和不一致性。根据文档,无论看到什么副作用,都不应手动调用layoutSubviews,即使这解决了您的问题(很可能是暂时的)。 - pronebird
1
如果您想知道如何解决iOS 9的这个问题,请参考:https://dev59.com/IGkw5IYBdhLWcg3wwNN5#32996503。 - pronebird
感谢您指引我们正确的方向。非常感激。 - Mahesh Agrawal

2

看起来由于某些原因,在动画触发之前您的UI并没有处于一个稳定的状态。

尝试在您的动画块之前添加调用[self.view layoutIfNeeded];,并在块的末尾使用[self.view layoutIfNeeded];而不是[self.view layoutSubviews];,后者在这种情况下不应该被使用。


2

针对 iOS 9 或更高版本,此解决方案可解决问题。

Objective-C:

 - (void)textFieldDidEndEditing:(UITextField *)textField
 {
    [textField layoutIfNeeded]; //Fixes iOS 9 text bounce glitch
    //...other stuff
 }

Swift:

  func textFieldDidEndEditing(_ textField: UITextField) {
    textField.layoutIfNeeded() //Fixes iOS 9 text bounce glitch
    //...other stuff
  }

我在谷歌上查到了这里。在@Mahesh Agrawal的回答下,@Andy评论了一个链接,该链接指向这里,这是我找到的解决此问题的最佳方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接