【问题标题】:UIKit: What happens when I have a UIView.animate inside an animation block?UIKit:当我在动画块中有 UIView.animate 时会发生什么?
【发布时间】:2021-01-09 04:03:10
【问题描述】:

通常在 swift 中,我可能想要一个属性,当设置时通常会产生动画。换句话说

class SelectableView: UIView {
   var isSelected: Bool = false {
      willSet {
        UIView.animate(withDuration: 0.200) {
           self.backgroundColor = .red
        }
      }
   }
}

但是,我意识到这可能不是最佳做法。例如,当我在其他地方使用我的课程时,我可能会不小心做了类似的事情:

let k = SelectableView()
UIView.animate(withDuration: 0.500) {
   k.isSelected = true
   k.alpha = 1.0
   k.backgroundColor = .red // notice this!
}

在那种情况下,甚至会发生什么?那里的行为到底是什么?颜色会在 500 毫秒还是 200 毫秒内变为红色? willSetdidSet 重要吗?如果我直接嵌套 UIView.animate 内联而不是在 setter 中会发生什么?

一般来说,在 setter 中有一个动画块可能是一种不好的做法吗?

【问题讨论】:

    标签: ios swift uiview uikit uiviewanimation


    【解决方案1】:

    在设置器中,您可以检查UIView.inheritedAnimationDuration 的值。如果为 0,则使用默认持续时间(即 0.2)。如果 > 0,则使用该值。另外,如果继承的duration>0,你可以跳过setter中的动画,直接赋值。

    class SelectableView: UIView {
       var isSelected: Bool = false {
          didSet {
            let duration = UIView.inheritedAnimationDuration
            UIView.animate(withDuration: duration > 0 ? duration : 0.200) {
               self.backgroundColor = .red
            }
          }
       }
    }
    

    就良好实践而言,Apple 在这种情况下使用了两个 setter:

    • isSelected - 没有隐式动画
    • setSelected(_ selected: Bool, animated: Bool) - 选择加入动画

    第一个可以是动态的,并使用animated: false 参数调用第二个。

    【讨论】:

      【解决方案2】:

      通常的做法是使用持续时间0。这意味着如果您在动画块中,您将从该动画块继承持续时间。

      因此,在您的示例中,如果 isSelected setter 观察者的动画持续时间为 0,则在动画块中设置 isSelected 的调用将以持续时间 0.5 进行动画处理。

      另外,我建议使用didSet 而不是willSet(不是出于任何特殊原因,我就是这样做的)。

      【讨论】:

      • 是的,但是如果我希望属性在动画块中没有的情况下以默认持续时间进行动画处理,该怎么办?
      • 我会使用层级动画来安排,所以我真的不知道。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      • 2016-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多