UIView 动画立即完成,不考虑持续时间或延迟

Posted

技术标签:

【中文标题】UIView 动画立即完成,不考虑持续时间或延迟【英文标题】:UIView animation is done instantly without regards to the duration or delay 【发布时间】:2016-11-08 16:18:25 【问题描述】:

我在为我的视图的 layoutConstraints 之一设置动画时遇到了一些困难:

UIView.animate(withDuration: 1, delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations: 
                self.topLayoutConstraint?.constant = self.currentYPosition
                self.layoutIfNeeded()
                , completion: nil)

无论我使用什么持续时间或延迟,动画都会立即完成(我的视图会从以前的位置跳转到新的位置)。

我检查了所有值,它们是正确的。 我也检查了,动画和完成都被调用了。

有什么想法吗?

编辑:

@objc private func viewDragged(_ recognizer: UIPanGestureRecognizer) 

        let location = recognizer.location(in: self.superview)

        switch recognizer.state 
        case .ended:

            if (recognizer.direction == .Down)             // Collapsing the slide panel

                currentYPosition = parentViewHeight - minimumVisibleHeight - statusBarHeight - navBarHeight
            
            else if (recognizer.direction == .Up)        // Expanding the slide panel

                // Substracting `minimumVisibleHeight` so that the dragable part is hidden behind the navigation bar
                currentYPosition = -minimumVisibleHeight
            

            self.topLayoutConstraint?.constant = self.currentYPosition
            UIView.animate(withDuration: 1, delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations: 
                self.layoutIfNeeded()
                , completion: nil)
            break
        case .began:
            HomeSlidePanelContainerView.draggingPreviousPosition = location.y
        default:
            self.layoutIfNeeded()

            if (location.y < (parentViewHeight - minimumVisibleHeight - statusBarHeight - navBarHeight)
                || location.y > (statusBarHeight + navBarHeight)) 

                currentYPosition -= HomeSlidePanelContainerView.draggingPreviousPosition - location.y
                topLayoutConstraint?.constant = currentYPosition
                self.layoutIfNeeded()
            
            HomeSlidePanelContainerView.draggingPreviousPosition = location.y
            break
        

    

【问题讨论】:

您是否尝试在layoutIfNeeded() 之前致电setNeedsUpdateConstraints() @werediver 喜欢在动画中还是之前?无论哪种情况,不,我没有 self.topLayoutConstraint?.constant = self.currentYPosition这一行从动画块中取出。 @holex 已经完成(见编辑),但没有任何变化 【参考方案1】:

我已经设法找到了解决方案。这可能对其他人有所帮助,所以我正在回答我自己的问题。

我正在做的事情是这样的:

self.topLayoutConstraint?.constant = self.currentYPosition

UIView.animate(withDuration: 1, delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations:                
                self.layoutIfNeeded()
, completion: nil)

如您所见,我正在更改一个值 topLayoutConstraint,这是对 self 的约束,即 UIView

然后我尝试通过在动画闭包中调用 self.layoutIfNeeded 来为该更改设置动画。

这里的事情是layoutIfNeeded() 适用于子视图而不是视图本身。所以在我的情况下,我试图为self 的子视图而不是self 本身的布局设置动画。

self.layoutIfNeeded() 更改为self.superview?.layoutIfNeeded() 和瞧!!

【讨论】:

我总是将 constraint.constant 设置为动画,但不知道它是如何工作的。需要检查文档。【参考方案2】:

在动画块之前设置约束:

self.topLayoutConstraint?.constant = self.currentYPosition

UIView.animate(withDuration: 1, delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations:                
                self.layoutIfNeeded()
, completion: nil)

【讨论】:

我认为错误在其他地方。也许发布更多代码。 默认值:case 和 .began case 没有动画。调试以确保您的情况正确。 我知道这一点。正如我所说,动画和完成块被执行......:/所以我的情况是正确的【参考方案3】:

我经常用Snapkit或者Masonry做自动布局,也许你可以试试。熟悉苹果的自动布局,很棒!例如我今天使用的子代码:

UIView.animate(withDuration: 1.0, animations: 
 minLabel.snp.updateConstraints  (make) in
            make.top.equalTo(view.snp.centerY)
                    
)
self.view.layoutIfNeeded()

【讨论】:

不想仅仅为了做一个动画而包含一个 pod:/ 但我同意,这是一个有趣的库 如果没有编译器错误并且当您刷新视图时,用户界面有时是正确的有时不是。这可能是线程问题。让您的动画和自动布局同步。

以上是关于UIView 动画立即完成,不考虑持续时间或延迟的主要内容,如果未能解决你的问题,请参考以下文章

动画立即结束,无论持续时间和延迟如何

核心动画立即调用完成函数

iOS - UIView 动画的限制?

如果不影响动画,则立即完成

UIView animateWithDuration 太快了

UIViewPropertyAnimator 不尊重持续时间和延迟参数