【问题标题】:Rotate UIButton 360 degrees旋转 UIButton 360 度
【发布时间】:2016-03-10 05:04:56
【问题描述】:

我一直在尝试使用以下代码运行将我的UIButton 旋转 360 度的动画:

UIView.animateWithDuration(3.0, animations: {
  self.vineTimeCapButton.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*2))
  self.instagramTimeCapButton.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*2))
})

但是,它不会旋转 360 度,因为 UIButton 已经在那个位置。

如何将我的 UIButton 旋转 360 度?

【问题讨论】:

    标签: ios swift uiview uibutton


    【解决方案1】:

    如果您需要多次执行此操作,您也可以尝试实现一个可以简化事情的扩展

    extension UIView {
        
        func rotate360Degrees(duration: CFTimeInterval = 1, repeatCount: Float = .infinity) {
            let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
            rotateAnimation.fromValue = 0.0
            rotateAnimation.toValue = CGFloat(Double.pi * 2)
            rotateAnimation.isRemovedOnCompletion = false
            rotateAnimation.duration = duration
            rotateAnimation.repeatCount = repeatCount
            layer.add(rotateAnimation, forKey: nil)
        }
        
        // Call this if using infinity animation
        func stopRotation () {
            layer.removeAllAnimations()
        }
    }
    

    【讨论】:

      【解决方案2】:

      斯威夫特 5。试试这个,它对我有用

      UIView.animate(withDuration: 3) {
        self.yourButton.transform = CGAffineTransform(rotationAngle: .pi)
        self.yourButton.transform = CGAffineTransform(rotationAngle: .pi * 2)
       }
      

      【讨论】:

        【解决方案3】:

        您可以使用一个技巧:先旋转 180 度,然后再旋转 360 度。使用 2 个延迟动画。 尝试这个。

        斯威夫特 2

        UIView.animateWithDuration(0.5) { () -> Void in
          button.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
        }
        
        UIView.animateWithDuration(0.5, delay: 0.45, options: UIViewAnimationOptions.CurveEaseIn, animations: { () -> Void in      
          button.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 2))
        }, completion: nil)
        

        斯威夫特 3、4、5

        UIView.animate(withDuration: 0.5) { () -> Void in
          self.settingsButton.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
        }
        
        UIView.animate(withDuration: 0.5, delay: 0.45, options: UIViewAnimationOptions.curveEaseIn, animations: { () -> Void in
          self.settingsButton.transform = CGAffineTransform(rotationAngle: CGFloat.pi * 2.0)
        }, completion: nil)
        

        希望对你有帮助

        【讨论】:

        • 你太棒了!!唯一的建议:为了使其平滑 360 度旋转,第二个“animateWithDuration”的延迟需要是动画持续时间的一半。非常感谢!!
        • 零延迟应该没问题!
        • 如何无限次重复此操作? option: .repeat ?
        【解决方案4】:

        Swift 4 版本,允许您无限次旋转同一个视图:

        UIView.animate(withDuration: 0.5) {
          self.yourButton.transform = self.yourButton.transform.rotated(by: CGFloat.pi)
        }
        

        如果要旋转 360°:

        UIView.animate(withDuration: 0.5) {
          self.yourButton.transform = self.yourButton.transform.rotated(by: CGFloat.pi)
          self.yourButton.transform = self.yourButton.transform.rotated(by: CGFloat.pi)
        }
        

        【讨论】:

        • 这不起作用,因为结束位置与开始位置相同。
        • @tobi,谢谢。我从未尝试过旋转 360°,所以我不知道它不起作用。我已经更新了处理这种情况的答案。
        • 对于 360 度版本,第二次变换旋转需要 2 * pi。即:self.yourButton.transform = self.yourButton.transform.rotated(by: CGFloat.pi * 2)
        • @Reefwing 你的建议有用吗?自从我编写上面的代码以来已经有一段时间了,但我认为我遇到了某种问题,如果旋转为pi*2(动画开始和结束的位置相同),按钮甚至不会动画。如果您可以确认pi*2 代码有效,我将更新我的答案。谢谢! (也许我今天晚些时候有时间自己测试一下)
        • @Reefwing 我刚刚测试过,如果我输入pi*2,它只会旋转180',而我发布的代码仍然为我执行360'。我暂时保留它,但如果人们出于某种原因与您有同样的问题,他们可以看到您的评论,这很好。
        【解决方案5】:

        您可以使用基于CABasicAnimation (Swift 4.x) 的小扩展:

        extension UIButton {
            func rotate360Degrees(duration: CFTimeInterval = 1.0, completionDelegate: AnyObject? = nil) {
                let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
                rotateAnimation.fromValue = 0.0
                rotateAnimation.toValue = CGFloat(.pi * 2.0)
                rotateAnimation.duration = duration
        
                if let delegate: AnyObject = completionDelegate {
                    rotateAnimation.delegate = delegate as? CAAnimationDelegate
                }
                self.layer.add(rotateAnimation, forKey: nil)
            }
        }
        

        用法

        例如我们可以开始做一个简单的按钮:

        let button = UIButton()
        button.frame = CGRect(x: self.view.frame.size.width/2, y: 150, width: 50, height: 50)
        button.backgroundColor = UIColor.red
        button.setTitle("Name your Button ", for: .normal)
        button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
        self.view.addSubview(button)
        

        然后我们可以构建它的选择器:

        @objc func buttonAction(sender: UIButton!) {
                print("Button tapped")
                sender.rotate360Degrees()
        }
        

        【讨论】:

        • UIView 扩展只能用于派生自UIView 的元素。不能用于UIBarButtonItem等元素
        • @Prashant 不,你错了。扩展不受您所说的限制。扩展为现有的类、结构、枚举或协议类型添加了新功能。这包括扩展您无权访问原始源代码的类型的能力(称为追溯建模)。如果您需要有关扩展的更多信息,请查看here
        • 我想说的是您的代码必须稍作修改才能用于 UIBarButtonItem 。对于从 UIView 派生的所有其他 UI 元素,可以添加上述扩展。以下是UIBarButtonItem 的情况self.layer.add(rotateAnimation, forKey: nil) 行将被修改为self.customView!.layer.add(rotateAnimation, forKey: nil)
        • 哦,当然,这是正确的,你有理由。我已经根据一个修改过的旧问题更新了我的旧答案(那是因为我们谈到了 UIBarButtonItem..),现在它可以工作了。
        【解决方案6】:

        正如here 所讨论的,您也可以使用CAAnimation。此代码应用一个完整的 360 度旋转:

        斯威夫特 3

        let fullRotation = CABasicAnimation(keyPath: "transform.rotation")
        fullRotation.delegate = self
        fullRotation.fromValue = NSNumber(floatLiteral: 0)
        fullRotation.toValue = NSNumber(floatLiteral: Double(CGFloat.pi * 2))
        fullRotation.duration = 0.5
        fullRotation.repeatCount = 1
        button.layer.add(fullRotation, forKey: "360")
        

        你需要导入QuartzCore:

        import QuartzCore
        

        而你的ViewController 需要符合CAAnimationDelegate

        class ViewController: UIViewController, CAAnimationDelegate {
        
        }
        

        【讨论】:

          【解决方案7】:

          Swift 4:动画嵌套闭包优于动画延迟块。

          UIView.animate(withDuration: 0.5, animations: { 
            button.transform = CGAffineTransform(rotationAngle: (CGFloat(Double.pi))) 
           }) { (isAnimationComplete) in
          
                 // Nested Block
          UIView.animate(withDuration: 0.5) { 
             button.transform = CGAffineTransform(rotationAngle: (CGFloat(Double.pi * 2)))
                 }    
          }
          

          【讨论】:

          • 我喜欢这个解决方案!
          【解决方案8】:

          在 Swift 3 中:

          UIView.animate(withDuration:0.5, animations: { () -> Void in
            button.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI))
          })
          
          UIView.animate(withDuration: 0.5, delay: 0.45, options: .curveEaseIn, animations: { () -> Void in
            button.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI * 2))
          }, completion: nil)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-01-11
            • 2012-04-08
            相关资源
            最近更新 更多