【问题标题】:Programmatically removing/adding constraints animated以编程方式删除/添加动画约束
【发布时间】:2016-10-14 12:40:24
【问题描述】:

我在使用动画以编程方式删除和添加约束时遇到了困难。我已将现有项目简化为一个小项目,仅用于演示。

设置是有两个(容器)视图:顶部和底部。它们包含两个子视图:蓝色和红色。

顶视图的纵横比限制为 2:3。

我参考了我在 viewDidLoad 中初始化的 topView、aspectRatioConstraint 和 heightConstraint

  @IBOutlet weak var aspectRatioConstraint: NSLayoutConstraint!

  var heightConstraint: NSLayoutConstraint!

  @IBOutlet weak var topView: UIView!

  override func viewDidLoad() {
    super.viewDidLoad()
    heightConstraint = NSLayoutConstraint(item: topView, attribute: .height, relatedBy: .equal, toItem: topView, attribute: .height, multiplier: 1.0, constant: topView.frame.size.height)
    NSLayoutConstraint.activate([heightConstraint])
    topView.removeConstraint(aspectRatioConstraint)
  }

  @IBAction func startAnimation(_ sender: AnyObject) {
    UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.1, options: .curveEaseIn, animations: {
      self.heightConstraint.constant = 20.0
      self.view.layoutIfNeeded()
      }, completion: nil)
  }

导航中的“+”按钮调用startAnimation方法,它应该在一段时间内调整heightConstraint的大小,但它没有。

我做错了什么?

示例项目 -> https://www.dropbox.com/sh/7i75i0zq9dormqb/AACzTYvWOoJL3MjcjgMIyOd9a?dl=0

【问题讨论】:

  • 有什么问题?调整大小没有动画或根本不调整大小?
  • 如何在 viewDidLoad 中激活约束?它应该会崩溃,因为当时约束还没有准备好。
  • @MaksTheAwesome 根本不会调整大小。 Dasem 我已经想通了。如果 heightConstraint 为 nil { init heightConst,激活它,删除 aspectRatioConst },我已经在 viewDidLayoutSubviews() 中实现

标签: ios swift constraints


【解决方案1】:

试试这个:

UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.1, options: .curveEaseIn, animations: {
      NSLayoutConstraint.deactivate([self.heightConstraint])
      self.heightConstraint.constant = 20.0
      NSLayoutConstraint.activate([self.heightConstraint])
      self.view.layoutIfNeeded()
  }, completion: nil)

您在更新某些约束之前已停用

【讨论】:

  • 您是否也尝试过:topView.layoutIfNeeded() 而不是 self.view ?
  • 我看到的最后一件事,您可以尝试更新所有约束,而不仅仅是常量。 self.heightConstraint = NSLayoutConstraint(item: topView, attribute: .height, relatedBy: .equal, toItem: topView, attribute: .height, multiplier: 1.0, constant: 20)
  • 我下载了您的项目,显然您的约束中有错误。首先修复它:)
  • 因为将视图的 frame.height 添加为恒定高度约束是没有意义的。您正在使用约束来避免使用静态框架。 raywenderlich.com/125718/coding-auto-layout
  • 这不是废话。纵横比约束将根据屏幕宽度调整视图大小,即对于 iPhone 6,它将是 375:250。现在知道框架的高度,计划是切换约束,因为不再需要方面。我想改变的是一些动作后的高度。
【解决方案2】:

由于子视图中的子视图,我对您的项目感到困惑,但我创建了自己的项目,应该可以满足您的需求。首先是关于您的项目的两个旁注:

(1) 您遇到的 AutoLayout 错误是在更改代码中的约束时出现的。我不知道为什么会这样……可能是因为你在彼此之间嵌套了全尺寸的子视图,或者其他什么。

(2) 我会在可能的情况下在 ViewDidLoad() 中更改/创建约束犹豫不决。 UIView 确实没有它需要的东西。我尝试在 ViewWillLayoutSubviews() 中进行约束更改。

这就是我所做的,基本上是您项目的一个子集:

(1) 在 IB 中设置你能做的。故事板中的两个视图(没有嵌套的子视图,尽管我认为它应该可以工作)。当然,还要连接导航控制器的添加按钮!

(2)添加以下约束:

顶视图:

-- 前导、尾随和顶部边距为 0 -- 纵横比为 3:2 -- 高度为 20

底视图:

-- 所有边距设置为 0

(3) 通过将Top View 高度的优先级从“必需”设置为“高”来纠正IB“错误”。

(4) 为视图控制器添加纵横比和高度约束的 IBOutlets。

(5) 以下代码(在您的项目中很接近)是您在视图控制器中所需要的全部内容。请注意,我在其他任何地方都添加了 no 代码:

@IBOutlet weak var heightRatio: NSLayoutConstraint!
@IBOutlet weak var aspectRatio: NSLayoutConstraint!

@IBAction func animateLayoutChange(_ sender: UIBarButtonItem) {
    UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.1, options: .curveEaseIn, animations: {
        self.aspectRatio.isActive = false
        self.heightRatio.isActive = true
        self.view.layoutIfNeeded()
        }, completion: nil)
}

【讨论】:

    【解决方案3】:

    试试这个:

    @IBAction func startAnimation(_ sender: AnyObject) {
    self.heightConstraint.constant = 20.0
        UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.1, options: .curveEaseIn, animations: {
    
          self.view.layoutIfNeeded()
          }, completion: nil)
      }
    

    【讨论】:

    • 早些时候尝试过,但没有帮助。谢谢
    【解决方案4】:

    如果你只想动画 topView 的高度,你可以试试这个:

    UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.1, options: .curveEaseIn, animations: {
        self.topView.frame.size.height = 20.0
        self.view.layoutIfNeeded()
    }, completion: nil)
    

    【讨论】:

    • 这就是约束的问题(好事)。如果您尝试更改视图的框架,约束不会让这种情况发生,也就是说它们会强制视图回到原位
    • 在示例应用程序中,您的目标是让 topView 高度 = 20,同时将 bottomView 的顶部约束固定到 topView 的底部边缘,对吧?
    • 没错。将高度约束更改为 20 应该让底视图展开
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    相关资源
    最近更新 更多