【问题标题】:Strange animation occurs when extending UIView扩展 UIView 时出现奇怪的动画
【发布时间】:2019-03-22 00:54:45
【问题描述】:

我有一个如下的 XUIView 类。当我运行动画时,折叠没有效果。

谁能解释一下?

类视图控制器:UIViewController { // XUIView 实例的宽度约束 @IBOutlet 弱变量 vwWrapperWidth:NSLayoutConstraint! { 设置{ self.vwWrapperWidth.constant = UIScreen.main.bounds.width } } @IBAction func btnToggleTouchUp(_ sender: UIButton) { 如果(self.vwWrapperWidth.constant == 55){ // 展开时动画效果OK self.vwWrapperWidth.constant = UIScreen.main.bounds.width UIView.animate(withDuration:0.5,动画:{ self.view.layoutIfNeeded() }) } 别的 { // 折叠时动画效果不行 self.vwWrapperWidth.constant = 55 UIView.animate(withDuration:0.5,动画:{ self.view.layoutIfNeeded() }) } } //..... } @IBDesignable 类 XUIView: UIView { @IBInspectable var roundTopLeftCorner: 布尔 = 假 @IBInspectable var roundBottomLeftCorner: Bool = false @IBInspectable var roundTopRightCorner: 布尔 = 假 @IBInspectable var roundBottomRightCorner: Bool = false @IBInspectable 变角半径:CGFloat = 0.0 @IBInspectable var 边界宽度:CGFloat = 0.0 @IBInspectable var 边框颜色:UIColor? fileprivate varborderLayer:CAShapeLayer? { 设置{ self.layer.addSublayer(self.borderLayer!) } } func roundCorners(_角:UIRectCorner){ if(self.borderLayer == nil) { self.borderLayer = CAShapeLayer() } 让边界 = self.bounds 让 maskPath = UIBezierPath(roundedRect:边界,byRoundingCorners:角,cornerRadii:CGSize(宽度:self.cornerRadius,高度:self.cornerRadius)) 让 maskLayer = CAShapeLayer() maskLayer.frame = 边界 maskLayer.path = maskPath.cgPath self.layer.mask = maskLayer self.borderLayer?.frame = 边界 self.borderLayer?.path = maskPath.cgPath self.borderLayer?.strokeColor = self.borderColor?.cgColor self.borderLayer?.lineWidth = self.borderWidth self.borderLayer?.fillColor = nil } 覆盖 func layoutSubviews() { super.layoutSubviews() var roundedCorners: UIRectCorner = [] 如果(roundTopLeftCorner){roundedCorners.insert(.topLeft)} if(roundTopRightCorner) { roundedCorners.insert(.topRight) } 如果(roundBottomLeftCorner){roundedCorners.insert(.bottomLeft)} 如果(roundBottomRightCorner){roundedCorners.insert(.bottomRight)} 圆角(圆角) } }

源代码:http://www.mediafire.com/file/n6svp1mk44fc0uf/TestXUIView.zip/file

【问题讨论】:

  • 尝试删除 vwWrapperWidth 中的 didSet
  • @elbertrivas,didSet 在初始化时被调用一次,所以这不是原因。

标签: swift


【解决方案1】:

“折叠”动画没有动画,因为 CALayerpath 属性不是隐式可动画的。提到了here

与大多数动画属性不同,路径(与所有 CGPath 动画属性一样)不支持隐式动画。

更糟糕的是,CALayerframe 属性也不是隐式可动画的。提到here

注意:frame 属性不能直接设置动画。相反,您应该对 bounds、anchorPoint 和 position 属性的适当组合进行动画处理,以获得所需的结果。

这只是意味着以下行将不起作用,因为它是在 UIView.animate 块内调用的。

let maskLayer = CAShapeLayer()
maskLayer.frame = bounds // This line won't animate!
maskLayer.path = maskPath.cgPath // This line won't animate!

self.layer.mask = maskLayer

因为它没有被动画化,所以只要调用XUIView 中的layoutSubviews 方法,就会应用蒙版。视图实际上是动画,但您只是无法看到它,因为蒙版是在动画完成之前设置的。

这也是展开动画中发生的情况。首先遮罩展开,然后出现动画。

为防止这种情况发生,您可能需要找到一种方法来为宽度约束图层框架和蒙版路径设置动画。

【讨论】:

    【解决方案2】:

    问题是您在layoutSubviews 中创建了一个CAShapeLayer,这意味着每次动画发生时都会调用它。

    尝试评论第 91 行,你会得到你想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-15
      • 1970-01-01
      • 2016-05-25
      • 2013-03-17
      • 2011-07-26
      • 2014-04-26
      • 1970-01-01
      相关资源
      最近更新 更多