Ios 更改viewController时保持动画
我试图在配置文件图片后面编写一个Ios 更改viewController时保持动画,ios,swift,animation,swift3,uiviewcontroller,Ios,Swift,Animation,Swift3,Uiviewcontroller,我试图在配置文件图片后面编写一个动画,以鼓励用户点击它。 这是一个越来越大越来越小的圆圈 override func layoutSubviews() { super.layoutSubviews() UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: { self.bouncedView.transform = CGAffineTransform
动画
,以鼓励用户点击它。
这是一个越来越大越来越小的圆圈
override func layoutSubviews() {
super.layoutSubviews()
UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {
self.bouncedView.transform = CGAffineTransform(scaleX:
1.3, y: 1.3)
}, completion: nil)
}
问题是,当我转到另一个
viewController
时,动画停止,圆圈保持在屏幕快照上的状态。你知道我怎样才能避免这个问题吗?嗯,我还没有一个令人满意的答案(至少这会让我满意),但我想至少补充一些我通过一点实验能够得到的见解
首先,当viewController
当前未显示时,动画似乎结束了。在您的情况下,这意味着动画将停止并以视图大1.3倍的状态结束,并停止重复<代码>布局子视图仅在第一次显示时才会被调用。至少viewController.viewdilayoutsubviews
仅在开始时调用,而不是在返回时调用(因此视图重新出现时将不会执行layoutSubviews
),因此动画不会重新启动
我试图将动画移动到UIViewController
的viewdide
——这也不起作用,因为停止动画会导致视图已缩放1.3倍的状态。在创建动画之前,将状态重置为CGAffineTransform.identity
正如我所说的,这可以作为一个解决办法,帮助您解决如何让它工作的问题,但是,我认为您真正需要的是一个钩子,它可以告诉您的视图(而不是viewController)它再次出现。但下面这个简单的例子至少可以帮助其他人看一看,而不是从头开始
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
let animator = UIViewPropertyAnimator(duration: 1, timingParameters: UICubicTimingParameters(animationCurve: .linear))
init(title: String) {
super.init(nibName: nil, bundle: nil)
self.title = title
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let animatableView = UIView()
override func loadView() {
let view = UIView()
view.backgroundColor = .white
animatableView.frame = CGRect(x: 150, y: 400, width: 100, height: 100)
animatableView.backgroundColor = UIColor.magenta
view.addSubview(animatableView)
self.view = view
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.animatableView.transform = CGAffineTransform.identity
UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {
self.animatableView.transform = CGAffineTransform(scaleX:
1.3, y: 1.3)
}, completion: nil)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("\(self.title) >> Lay out")
}
}
let tabBar = UITabBarController()
tabBar.viewControllers = [MyViewController(title: "first"), MyViewController(title: "second"), MyViewController(title: "third")]
tabBar.selectedIndex = 0
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = tabBar
编辑
我添加了几行代码来检查self.animatableView.layer.animationKeys()是否包含任何动画,切换选项卡似乎会将动画从视图的层中移除,因此每次视图重新出现时,您都必须找到添加动画的方法
编辑2
因此,我会使用@SWAT的答案,并使用
willMove(toWindow:)
而不是布局子视图
嗯,我还没有一个令人满意的答案(至少这会让我满意),但我想至少添加一些我能够通过一点实验获得的见解
首先,当viewController
当前未显示时,动画似乎结束了。在您的情况下,这意味着动画将停止并以视图大1.3倍的状态结束,并停止重复<代码>布局子视图仅在第一次显示时才会被调用。至少viewController.viewdilayoutsubviews
仅在开始时调用,而不是在返回时调用(因此视图重新出现时将不会执行layoutSubviews
),因此动画不会重新启动
我试图将动画移动到UIViewController
的viewdide
——这也不起作用,因为停止动画会导致视图已缩放1.3倍的状态。在创建动画之前,将状态重置为CGAffineTransform.identity
正如我所说的,这可以作为一个解决办法,帮助您解决如何让它工作的问题,但是,我认为您真正需要的是一个钩子,它可以告诉您的视图(而不是viewController)它再次出现。但下面这个简单的例子至少可以帮助其他人看一看,而不是从头开始
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
let animator = UIViewPropertyAnimator(duration: 1, timingParameters: UICubicTimingParameters(animationCurve: .linear))
init(title: String) {
super.init(nibName: nil, bundle: nil)
self.title = title
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let animatableView = UIView()
override func loadView() {
let view = UIView()
view.backgroundColor = .white
animatableView.frame = CGRect(x: 150, y: 400, width: 100, height: 100)
animatableView.backgroundColor = UIColor.magenta
view.addSubview(animatableView)
self.view = view
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.animatableView.transform = CGAffineTransform.identity
UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {
self.animatableView.transform = CGAffineTransform(scaleX:
1.3, y: 1.3)
}, completion: nil)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("\(self.title) >> Lay out")
}
}
let tabBar = UITabBarController()
tabBar.viewControllers = [MyViewController(title: "first"), MyViewController(title: "second"), MyViewController(title: "third")]
tabBar.selectedIndex = 0
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = tabBar
编辑
我添加了几行代码来检查self.animatableView.layer.animationKeys()是否包含任何动画,切换选项卡似乎会将动画从视图的层中移除,因此每次视图重新出现时,您都必须找到添加动画的方法
编辑2
因此,我会使用@SWAT的答案,使用
willMove(toWindow:)
而不是layoutSubviews
进行转换。视图上的标识已出现。类似于以下代码的内容:
class HomeController: UIViewController {
@IBOutlet weak var viewToAnimate: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
self.viewToAnimate.transform = .identity
animateView()
}
func animateView(){
UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {
self.viewToAnimate.transform = CGAffineTransform(scaleX:
1.3, y: 1.3)
}, completion: nil)
}
}
您可能已经猜到的问题是,UIView.animate仅在ViewDidLoad方法上调用,并且由于我们在从另一个ViewController返回此ViewController时没有访问该代码的权限,因此最好在ViewWillAspect方法中启动动画
如果在选项卡之间切换时出现相同问题,请为要设置动画的视图创建一个单独的UIView子类,并按以下步骤进行操作:
class AnimateView: UIView {
override func awakeFromNib() {
super.awakeFromNib()
}
override func willMove(toWindow newWindow: UIWindow?) {
super.willMove(toWindow: newWindow)
self.transform = .identity
animateView()
}
func animateView(){
UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {
self.transform = CGAffineTransform(scaleX:
1.3, y: 1.3)
}, completion: nil)
}
}
在这里,您已将动画功能应用于UIView对象,并且每当视图出现时,动画都将被重置。对ViewDidDisplay上的.identity进行转换。类似于以下代码的内容:
class HomeController: UIViewController {
@IBOutlet weak var viewToAnimate: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
self.viewToAnimate.transform = .identity
animateView()
}
func animateView(){
UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {
self.viewToAnimate.transform = CGAffineTransform(scaleX:
1.3, y: 1.3)
}, completion: nil)
}
}
您可能已经猜到的问题是,UIView.animate仅在ViewDidLoad方法上调用,并且由于我们在从另一个ViewController返回此ViewController时没有访问该代码的权限,因此最好在ViewWillAspect方法中启动动画
如果在选项卡之间切换时出现相同问题,请为要设置动画的视图创建一个单独的UIView子类,并按以下步骤进行操作:
class AnimateView: UIView {
override func awakeFromNib() {
super.awakeFromNib()
}
override func willMove(toWindow newWindow: UIWindow?) {
super.willMove(toWindow: newWindow)
self.transform = .identity
animateView()
}
func animateView(){
UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {
self.transform = CGAffineTransform(scaleX:
1.3, y: 1.3)
}, completion: nil)
}
}
在这里,您已将动画功能应用于UIView对象,并且每当视图出现时,动画都将重置。您所说的“当我更改
视图控制器时”
是什么意思?如果您正在某个地方进行编辑,您是否会在此基础上提供其他UIViewController,或者是什么原因导致动画停止?最好也包括代码抱歉,它不是很清楚。。。我的意思是,例如,当我更改选项卡时,或者当我转到另一个viewControllerOK时,因此当您将选项卡更改为另一个viewControllerOK时,动画会在其所在位置暂停