我正在制作一个应用程序,其中有一个 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 中添加了一些东西,但它仍然不起作用:
View Controller :
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
}
应用委托(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( fatal error ...可选值为 nil),因此它崩溃了。
请帮忙。提前致谢...安东
最佳答案
您需要稍微了解一下动画的工作原理。这在 WWDC session 236 'Building Interruptible and Responsive Interactions' 中有很好的解释。 (您感兴趣的部分从 17:45 开始)。同时,阅读有关 CABasicAnimation
的内容,并检查 CALayer
上的 presentationLayer
属性(您需要下拉到 CALayer
为你想要实现的目标,也许你需要使用 CA(Basic)Animation
来实现动画,尽管 UIKit 的动画方法可能仍然可以做到这一点,如果你有结构良好的代码)。
基本上, View 或层将立即获得您设置为动画一部分的最终值。然后动画开始,从头到尾。如果动画被打断,比如离开应用程序,返回时将使用它具有的值绘制 View (当动画消失时,这些值是最终值)。
你想要的是当你离开应用程序时在动画中的那个点捕获 View 的值,保存它,并在你的应用程序返回前台时从那个点到原始端点开始一个新的动画.您可以通过从 CALayer
请求框架或变换来获取 CALayer
(不是 UIView
)的当前位置,无论您需要什么的 presentationLayer
属性。
我在构建用于任何 `UIScrollView`` 的自定义 refreshControl 时遇到了这个问题。这段代码在 Github 上,你的相关代码在这里(它是 Objective-C,但不是很复杂,所以你应该能够跟随并在 Swift 中重新实现你需要的东西): JRTRefreshControlView.m ,具体来说:
-(void)willMoveToWindow:(UIWindow *)newWindow
当用户将应用程序移至后台时,或者当 View 从 superView 中移除时(newWindow 将为 nil),这将被调用。
而子类中动画的实际实现在这里: JRTRotatingRefreshControlView.m , 特别是
- (void) resumeRefreshingState
方法就是你要看的。
(还有 saveRefreshingState
,您可以在其中保存来自 presentationLayer 的表示值,但我的动画没有实现它)。
关于ios - 当用户离开并返回应用程序时如何防止动画完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34822161/