我试图在一个循环中有一个明星“呼吸”的图像。变得更大然后更小然后重复自己。我希望在我的应用程序仍在运行并且响应时继续此操作。当我在我的应用程序中转到另一个视图时,我希望动画停止。
这就是我得到的
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
self.animateStars()
}
}
func animateStars() {
UIView.animate(withDuration: 4, animations : {
self.star.transform = CGAffineTransform(scaleX: 2.5, y: 2.5)
}) { finished in
NSLog("Star is big. Finished = \(finished)")
}
UIView.animate(withDuration: 4, animations : {
self.star.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
}) { finished in
NSLog("Star is small. Finished = \(finished)")
}
}
这并不困难。而且我不知道如何让它循环而不会在背景中像疯了一样运行,当用户点击带有segue的按钮时,转到另一个视图。
我在Objective C中找到了一个解决方案,但我似乎无法理解如何将其转换为Swift 3.0。示例:https://stackoverflow.com/a/31978173/5385322
[UIView animateWithDuration:1
delay:0
options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
animations:^{
yourView.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:nil];
感谢您的时间和建议! //西蒙
您发布的Objective-C重复动画代码的Swift版本将是:
UIView.animate(withDuration: 1.0,
delay: 0,
options: [.autoreverse, .repeat, .allowUserInteraction],
animations: {
self.star.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
},
completion: nil
)
(在Swift中,大多数选项标志参数,如该动画代码中的options
参数都是OptionSet
类型,它是支持Swift Set
语法的位标志,因此您可以在方括号中列出所需的选项,以逗号分隔。
请注意,@ TungFam的解决方案不能像编写的那样工作,但如果您使用检查animate
布尔值的完成块并且如果它是真的则重新调用动画方法,那么您可以使用该方法。
如果要停止动画,请使用
self.star.layer.removeAllAnimations()
self.star.layer.transform = CGAffineTransform.identity
如果您希望能够随意启动和停止动画,可以使用以下代码:
func animateView(_ view: UIView, animate: Bool) {
if animate {
UIView.animate(withDuration: 1.0,
delay: 0,
options: [.autoreverse, .repeat, .allowUserInteraction],
animations: {
view.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
},
completion: nil
)
} else {
self.button.layer.removeAllAnimations()
UIView.animate(withDuration: 1.0,
delay: 0,
options: [.curveEaseOut, .beginFromCurrentState, .allowUserInteraction],
animations: {
view.transform = CGAffineTransform.identity
},
completion: nil
)
}
}
当动画停止时,该代码将使视图平滑地动画回到正常大小。它还会为动画添加.allowUserInteraction标志,以防您正在制作动画的视图是一个按钮,您希望在它的大小发生变化时能够点按这个按钮。
尝试添加包含bool值的变量,该值表示需要设置动画。当用户点击按钮进入下一个屏幕时更改它。
像这样的东西:
var animate = true
override func viewDidLoad() {
super.viewDidLoad()
self.animateStars()
}
func animateStars() {
while animate == true {
// breathing animation
}
}
@IBAction func buttonPressed(_ sender: UIButton) {
animate = false
// perform your segue
}
如果您想在用户返回此屏幕时再次将其设置为动画,请将self.animateStars()
放置到viewWillAppear
方法中。
通过@DuncanC的一些见解,我能够很好地使用它。当我转到另一个视图时动画现在停止,当我回到原始视图时动画继续。
代码如下所示:
class MainViewController: UIViewController {
@IBOutlet weak var star: UIImageView!
var queue = DispatchQueue.main
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.star.layer.removeAllAnimations()
self.star.transform = CGAffineTransform.identity
queue.async {
self.animateStars()
}
}
@IBAction func someAction(_ sender: Any) {
performSegue(withIdentifier: "someSegue", sender: self)
}
func animateStars() {
UIView.animate(withDuration: 1,
delay: 0,
options:[.autoreverse, .repeat],
animations : {
self.star.transform = CGAffineTransform(scaleX: 2.5, y: 2.5)})
{ finished in
UIView.animate(withDuration: 1.0,
delay: 0,
options: [.curveEaseOut, .beginFromCurrentState],
animations: {
self.star.transform = CGAffineTransform.identity
},
completion: nil
)
}
UIView.animate(withDuration: 1,
delay: 0,
options: [.autoreverse, .repeat],
animations: { self.star.transform = CGAffineTransform(scaleX: 2.5, y: 2.5) })
}
}
我对编程仍然很陌生,去上学,到目前为止我还没有学到如此多的测试。因此,我没有测试这个内存泄漏和诸如此类的东西。但代码有效,这意味着我现在很高兴。
感谢大家的帮助!如果您认为可以改进代码,请提供建议。 :)
//西蒙