【问题标题】:Animate views constraint without animating other views动画视图约束而不动画其他视图
【发布时间】:2016-10-04 13:46:14
【问题描述】:

当用户从 textField 移动到 textField 时,我正在尝试为 viewController 中的所有视图设置动画(向上和向下),其中每个 textField 都有一个不同高度的键盘,并且我正在使用自动布局来定位所有意见。

我有四个UITextFields 和三个UIButtons 使用自动布局并根据不同的键盘高度上下移动,我的问题是,由于某种原因,所有视图都会在 viewController 加载后立即动画这不是我想要的,我只希望它们在键盘高度不同时制作动画。动画看起来就像是在加载 viewController 后立即为所有视图的大小和位置设置动画。

为了驱动动画,我有一个主要约束 (constraintKeyboardHeight),所有视图都附加到其中以确定它们的垂直位置(见下图)。

仅供参考 - 请注意,我正在自动聚焦 viewDidLoad 方法中的一个文本字段。我不确定这是否与它有关。

有什么想法吗?在为带有约束的视图设置动画时,这是正常行为吗?

    override func viewDidLoad() {
     super.viewDidLoad()

     oneTextField.becomeFirstResponder()

     NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UserInputViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
}


func keyboardWillShow(notification: NSNotification) {
      if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {

      keyboardHeight = keyboardSize.height + 10

      UIView.animateWithDuration(3.0, animations: {
        self.constraintKeyboardHeight.constant = keyboardHeight
        self.view.layoutIfNeeded()
      })
    }
}

【问题讨论】:

    标签: ios swift animation autolayout uikit


    【解决方案1】:

    调用self.view.layoutIfNeeded 将触发视图中所有内容的布局更新。如果这包括您不想制作动画的子视图,您应该将所有您想要制作动画的子视图添加到容器子视图中。基于键盘约束容器子视图,仅在该子视图上调用layoutIfNeeded。

    我有点困惑

    我的问题是,由于某种原因,所有视图都会在 viewController 加载后立即进行动画处理,这不是我想要的,我只希望它们在键盘高度不同时进行动画处理

    我将此问题解释为“所有视图都具有动画效果”,而您只需要其中的一些视图。如果问题更多是关于立即动画的视图,那当然会发生,因为您在视图加载时设置了第一响应者。

    编辑:如果您不想在第一次加载时设置动画,可以在控制器中添加属性var firstLoad = true,然后修改键盘将显示如下功能:

    func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo [UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            keyboardHeight = keyboardSize.height + 10
            self.constraintKeyboardHeight.constant = keyboardHeight
            if firstLoad {
                view.layoutIfNeeded()
                firstLoad = false
            } else {
                UIView.animateWithDuration(3.0, animations: {
                    self.view.layoutIfNeeded()
                })
            }
        }
    }
    

    您会注意到我将约束常量线移出动画块。您实际上不需要动画块中的这一行,只需 layoutIfNeeded 调用即可。

    【讨论】:

    • @ Connor Neville - 问题是视图立即动画化,但显然这是预期的行为。如果我理解正确self.view.layoutIfNeeded 正在从 viewController 直接更新主视图中的所有视图,但是如果我只指定为其中一个约束设置动画,为什么动画会应用于所有视图、位置和大小?我希望为所有视图设置动画,但只能上下调整以适应该约束的值。
    • 动画立即发生,因为键盘立即出现,这对我来说听起来很明智,但如果您不想在第一次加载时出现动画,您可以为第一次加载设置某种布尔标志.是的,这是 layoutIfNeeded 的预期行为,因为一个约束更改可以而且经常会更改整个视图的布局。
    • @Connor Neville - 现在有意义了。还有一个问题:如何跟踪负载?这可以解决我的问题,因为动画工作正如我在第一次加载后所期望的那样。如果这太复杂了,我将按照您的答案中的建议将视图添加到单个视图中。但我很好奇这是如何做到的。谢谢。
    • 将其编辑到我的评论中。
    • 你太棒了,非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-21
    • 2018-06-16
    相关资源
    最近更新 更多