【问题标题】:Why UIView animation fails when text within the UIView is changed before the animation?当 UIView 中的文本在动画之前更改时,为什么 UIView 动画会失败?
【发布时间】:2026-01-22 22:35:01
【问题描述】:

我对@9​​87654323@ 动画比较陌生,并且制作了一个简单的“infoView”帧的上/下动画。

深蓝色区域是可触摸的,并且可以切换到目前为止效果很好的动画。

问题只是右上角UILabel的TEXT变化。如果我在动画完成块之前、之后或中更改标签的内容,动画总是失败。 -> 然后它不再动画了......它似乎闪烁了一次。我不知道这里有什么问题......

一些代码: 我保存动画的两个帧位置:

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        infoViewRectNotVisible = infoView.frame
        infoViewRectVisible = CGRect(x: infoView.frame.minX, y: searchBar.frame.minY, width: infoView.frame.width, height: infoView.frame.height)
 }

我只是让 infoView 上下动画:

@IBAction func infoButtonPressed(_ sender: Any) {
        infoIsVisible = !infoIsVisible

        showHideLabel.text = infoIsVisible ? "hide Info" : "show Info"

        print(infoView.frame)
        print(infoViewRectVisible)
        print(infoViewRectNotVisible)

        UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut, animations: {
            self.infoView.frame = self.infoIsVisible ? self.infoViewRectVisible : self.infoViewRectNotVisible
        })
}

如果我发表评论 showHideLabel.text = infoIsVisible ? "hide Info" : "show Info" out,动画按照接受的方式工作,否则它不再动画了

infoIsVisible Bool 和保存的帧(infoViewRectVisible 和 infoViewRectNotVisible)总是正确的。

我试过了:

  • .setNeedsLayout(), .layoutIfNeeded()
  • 在动画的完成块中设置文本
  • .translatesAutoresizingMaskIntoConstraints 为假
  • ....

我真的不知道为什么我不能更改文本 - 还是我完全误解了什么?

感谢您的帮助!

【问题讨论】:

  • 您是否使用 Autolayout/SnapKit 将标签定位在蓝色视图内?
  • 嘿,是的,标签位于顶部,在 Autolayout 的右侧。
  • 因此,当您更改文本时,标签会将其框架更改为intrinsicContentSize 以适应新内容。之后它可能会隐式调用setNeedsLayout,所以我猜 Autolayout 基本上会干扰您的手动 UIView 动画。您可以尝试为标签设置固定大小限制并重试吗?
  • 与其手动更改infoView 的框架,不如尝试设置其顶部约束,根据infoIsVisible 更改其constant 属性,然后在UIView.animate... 块内调用infoView.setNeedsLayout()
  • 问题是您将约束与设置框架属性混合在一起。你应该只做其中之一。改为使用约束进行动画处理。

标签: ios swift animation uiview


【解决方案1】:

您无需为帧设置动画即可获得所需的结果。您可以只为正确的视图变换设置动画:

let yTranslation = CGAffineTransform(
    translationX: 0.0,
    y: infoView.frame.height - searchBar.frame.height
)

UIView.animate(
    withDuration: 0.3,
    delay: 0,
    options: .curveEaseInOut,
    animations: {
        self.infoView.transform = self.infoIsVisible ? yTranslation : .identity
    }
)

【讨论】: