我正在创建一个应用程序,我有一个button
从屏幕的一侧移动到另一侧。我创建了一个暂停button
,在选择button
后暂停动画。这个button
和函数工作正常。我还添加了一个函数,用于确定用户是否已退出应用程序。在这个函数中,我添加了暂停button
函数。但是,当用户退出后返回应用程序时,它会显示暂停屏幕,但动画已完成。这是代码:
@IBAction func pauseButton(sender: UIButton) {
let button = self.view.viewWithTag(1) as? UIButton!
let layer = button!.layer
pauseLayer(layer) // Pausing the animation
view2.hidden = false // Showing pause screen
}
func pauseLayer(layer: CALayer) {
let pausedTime: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
}
@IBAction func startButton(sender: UIButton) {
let button = UIButton()
button.tag = 1 // so I can retrieve it in the pause function
// Extra code to make the button look nice
button.translatesAutoresizingMaskIntoConstraints = false // Allow constraints
let topAnchorForButton = button.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 400)
NSLayoutConstraint.activateConstraints([ // Adding constraints
topAnchorForButton,
button.leadingAnchor.constraintEqualToAnchor(view.topAnchor, constant: 120),
button.widthAnchor.constraintEqualToConstant(65),
button.heightAnchor.constraintEqualToConstant(65)
])
self.view.layoutIfNeeded()
[UIView.animateWithDuration(5.0, delay: 0.0, options: [.CurveLinear, .AllowUserInteraction], animations: {
topAnchorForButton.constant = 0
self.view.layoutIfNeeded()
}, completion: nil )] // the animation
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "pauseButton:", name: UIApplicationWillResignActiveNotification, object: nil) // When exists app
NSNotificationCenter.defaultCenter().addObserver(self, selector: "pauseButton:", name: UIApplicationDidEnterBackgroundNotification, object: nil) // when goes to home screen
}
当我重新进入应用程序时,动画已完成。
这是我尝试过的代码,只播放和停止动画。我还在App Delegate中添加了一些东西,但它仍然不起作用:
的ViewController:
class Home: UIViewController {
func pauseAnimation(){
let button = self.view.viewWithTag(1) as? UIButton!
let layer = button!.layer
pauseLayer(layer) // Pausing the animation
}
@IBAction func pauseButton(sender: UIButton) {
pauseAnimation()
}
func pauseLayer(layer: CALayer) {
let pausedTime: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
}
@IBAction func startButton(sender: UIButton) {
let button = UIButton()
button.tag = 1 // so I can retrieve it in the pause function
// Extra code to make the button look nice
button.setTitle("Moving", forState: .Normal)
button.setTitleColor(UIColor.redColor(), forState: .Normal)
view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false // Allow constraints
let topAnchorForButton = button.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 400)
NSLayoutConstraint.activateConstraints([ // Adding constraints
topAnchorForButton,
button.leadingAnchor.constraintEqualToAnchor(view.topAnchor, constant: 120),
button.widthAnchor.constraintEqualToConstant(65),
button.heightAnchor.constraintEqualToConstant(65)
])
self.view.layoutIfNeeded()
[UIView.animateWithDuration(10.0, delay: 0.0, options: [.CurveLinear, .AllowUserInteraction], animations: {
topAnchorForButton.constant = 0
self.view.layoutIfNeeded()
}, completion: nil )] // the animation
}
App Delegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var vc = Home()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
}
func applicationWillResignActive(application: UIApplication) {
vc.pauseAnimation()
}
万一你想知道,这是恢复动画的代码:
@IBAction func resume(sender: UIButton) {
let button = self.view.viewWithTag(100) as? UIButton!
let layer = button!.layer
resumeLayer(layer)
}
func resumeLayer(layer: CALayer) {
let pausedTime: CFTimeInterval = layer.timeOffset
layer.speed = 1.0
layer.timeOffset = 0.0
layer.beginTime = 0.0
let timeSincePause: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
layer.beginTime = timeSincePause
}
退出应用时,它表示button
或/和layer
为零(致命错误...可选值为nil),因此崩溃。
请帮忙。在此先感谢...安东
答案 0 :(得分:1)
尝试将此代码放入:
查看控制器:
pauseAnimation(){
let button = self.view.viewWithTag(1) as? UIButton!
let layer = button!.layer
pauseLayer(layer) // Pausing the animation
view2.hidden = false // Showing pause screen
}
的AppDelegate:
func applicationWillResignActive(application: UIApplication) {
vc.pauseAnimation()
}
为了能够从appDelegate中的视图控制器访问功能,请转到此处:link
答案 1 :(得分:1)
看看here。清单5-4显示了如何暂停和恢复动画的示例。您应该将代码移出AppDelegate,而视图控制器(Home)应该处理进出后台的问题。在首页的viewDidLoad
或viewWillAppear
:
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "resigningActive",
name: UIApplicationWillResignActiveNotification,
object: nil
)
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "becomeActive",
name: UIApplicationDidBecomeActiveNotification,
object: nil
)
你可能需要removeObserver
,可能是在家里的deinit。然后你有:
func resigningActive() {
pauseLayer(button!.layer)
}
func becomeActive() {
resumeLayer(button!.layer)
}
此代码不需要另一个按钮来暂停/恢复,但如果需要,您也可以这样做。您可能需要在viewWillAppear
中定义观察者,因为看起来您的代码将引用出口而不是viewDidLoad
中尚未存在的出口。这意味着您必须编写代码才能在第一次调用viewWillAppear
时挂钩观察者,或者您将为同一事件添加多个观察者。
你的pauseLayer也应该将pausedTime写入NSUserDefaults,而resumeLayer应该按照(未经测试)的方式将其读回:
// Write
NSUserDefaults.standarduserDefaults().setDouble(Double(pausedTime), forKey: "pausedTime")
// Read
pausedTime = CFTimeInterval(NSUserDefaults.standarduserDefaults().doubleForKey("pausedTime"))
答案 2 :(得分:1)
您需要了解动画如何在幕后工作。这在WWDC session 236 'Building Interruptible and Responsive Interactions'(你感兴趣的部分从17:45开始)中得到了很好的解释。在此期间,请阅读CABasicAnimation
,并查看presentationLayer
上的CALayer
媒体资源(您需要下载到CALayer
了解您想要达到的目标,也许您将需要使用CA(Basic)Animation
来实现动画,尽管如果您已经很好地构建了代码,UIKit的动画方法可能仍然可以做到这一点。
基本上,视图或图层会立即获得您设置为动画一部分的结束值。然后动画从开始到结束开始。如果动画被中断,比如离开应用程序,在返回时,视图将使用它具有的值绘制(这是结束值,因为动画消失了)。
你想要的是当你离开应用程序时保存动画中的视图值,保存它,并在你的应用程序回到前台时从该点开始一个新动画到原始端点。您可以通过CALayer
{{1} UIView
{{1}请求框架或转换,获取您需要的任何内容,从而获得CALayer
(不是presentationLayer
)的当前位置} property。
构建自定义refreshControl以在任何`UIScrollView``中使用时,我遇到了这个问题。这段代码在Github上,你的相关代码在这里(它的Objective-C,但它不是很复杂,所以你应该能够跟随并重新实现你在Swift中所需的代码): JRTRefreshControlView.m,具体来说:
-(void)willMoveToWindow:(UIWindow *)newWindow
当用户将应用程序移动到后台时,或者从superView中删除视图时,会调用此方法(newWindow将为nil)。
子类中动画的实际实现如下: JRTRotatingRefreshControlView.m,特别是
- (void) resumeRefreshingState
方法是您想要查看的内容。
(还有saveRefreshingState
,你可以在这里保存presentationLayer中的表示值,但是我的动画没有实现它。