【问题标题】:For `UIView.animate`, is it possible to *chain* Swift Trailing Closures?对于 `UIView.animate`,是否可以 *chain* Swift 尾随闭包?
【发布时间】:2020-05-11 21:25:13
【问题描述】:

在 Swift 中,我希望对UIView.animate 进行多次调用。也就是说,当一个动画完成时,我希望另一个动画在之后继续,依此类推。

UIView.animate 的调用有一个Trailing Closure,我目前正在使用它来对UIView.animate 进行第二次调用。

问题是:我想做N个单独的动画

来自UIView.animate 的 Apple 文档

completion 动画序列结束时要执行的块对象。此块没有返回值,并采用单个布尔参数,指示动画是否在调用完成处理程序之前实际完成。如果动画的持续时间为 0,则在下一个 run loop 循环开始时执行此块。该参数可能为NULL。


理想情况下,我想遍历一组动画durations 并在对animate()的调用中使用

例如,

目标

遍历一个数组并为每个动画应用这些参数

  • let duration = [3.0, 5.0, 10.0]
  • let alpha = [0.1, 0.5, 0.66]
  • Xcode 版本 11.4.1 (11E503a)

我尝试过的

使用map 进行迭代,并且????希望它有效

  • 问题是只出现最终动画。所以系列中没有任何内容
  • 研究问:我是否需要在UIView 中设置一个布尔值,表示动画是连续发生的?
let redBox = UIView()
redBox.backgroundColor = UIColor.red
self.view.addSubview(redBox)

let iterateToAnimate = duration.enumerated().map { (index, element) -> Double in
  print(index, element, duration[index])

  UIView.animate(withDuration: duration[index],  // set duration from the array
                 animations:  { () in
                   redBox.alpha = alpha[index]
                 }, completion:{(Bool)  in
                      print("red box has faded out")
  })
}

如何制作一个动画

let redBox = UIView()
redBox.backgroundColor = UIColor.red
self.view.addSubview(redBox)

// One iteration of Animation
UIView.animate(withDuration: 1,
               animations:  { () in
                 redBox.alpha = 0
               }, completion:{(Bool)  in
                    print("red box has faded out")
})

链接两个animate 迭代的丑陋方式(希望避免)

// two iterations of Animation, using a trailing closure
UIView.animate(withDuration: 1,
               animations:  { () in
                 redBox.alpha = 0
               }, completion:{(Bool)  in
                    print("red box has faded out")

}) { _ in  // after first animation finishes, call another in a trailing closure
  UIView.animate(withDuration: 1,
                 animations:  { () in
                   redBox.alpha = 0.75
                 }, completion:{(Bool)  in
                      print("red box has faded out")

  }) // 2nd animation
}

【问题讨论】:

    标签: ios swift animation closures uiviewanimation


    【解决方案1】:

    如果参数很少并且在编译时已知,则构建链接动画的最简单方法是作为关键帧动画的帧。

    如果参数在编译时未知(例如,您的持续时间将在运行时到达)或者参数很多并且写出关键帧动画太麻烦,那么只需放置一个动画及其完成处理程序变成一个函数并递归。简单示例(适应自己的目的):

    var duration = [3.0, 5.0, 10.0]
    var alpha    = [0.1, 0.5, 0.66] as [CGFloat]
    
    func doTheAnimation() {
        if duration.count > 0 {
            let dur = duration.removeFirst()
            let alp = alpha.removeFirst()
            UIView.animate(withDuration: dur, animations: {
                self.yellowView.alpha = alp
            }, completion: {_ in self.doTheAnimation()})
        }
    }
    

    【讨论】:

    • 递归完成处理程序是一个非常优雅的解决方案。我永远不会知道编译时的参数计数。 .removeFirst() 也是一个很好的提示。它就像一个魅力。
    【解决方案2】:

    你可以使用UIView.animateKeyframes

           UIView.animateKeyframes(withDuration: 18.0, delay: 0.0, options: [], animations: {
                UIView.addKeyframe(withRelativeStartTime: 3.0/15.0, relativeDuration: 3.0/15.0, animations: {
                    self.redBox.alpha = 0
                })
                UIView.addKeyframe(withRelativeStartTime: 8.0/15.00, relativeDuration: 5.0/15.0, animations: {
                   self.redBox.alpha = 0.75
                })
            }) { (completed) in
               print("completed")
            }
    

    【讨论】:

    • 这看起来也很有希望。
    • @RobLabs 您可能还记得那也是我回答中的 first 内容。这是一个好方法,只是配置工作要多一点。
    • 谢谢@matt — 你的答案首先出现,当我在我的代码中测试你的解决方案时,Arun 进来了。
    • 哦,这不是问题。关键是,两种方式都很好。每个都有它的位置。你应该两个都试试!
    猜你喜欢
    • 2018-03-27
    • 1970-01-01
    • 2020-10-09
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多