Wiederherstellen der Animation an der Stelle, an der sie abgebrochen wurde, wenn die App vom Hintergrund aus fortgesetzt wird
Habe ich eine endlos Schleife CABasicAnimation
einer sich wiederholenden Bildelementen aus meiner Sicht:
a = [CABasicAnimation animationWithKeyPath:@"position"];
a.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionLinear];
a.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
a.toValue = [NSValue valueWithCGPoint:CGPointMake(image.size.width, 0)];
a.repeatCount = HUGE_VALF;
a.duration = 15.0;
[a retain];
Ich habe versucht, die "anhalten und fortsetzen" layer animation wie beschrieben in Technische Q&A QA1673.
Wenn die app tritt in den hintergrund, die animation wird aus der Ebene entfernt.
Zum Ausgleich höre ich UIApplicationDidEnterBackgroundNotification
- und call - stopAnimation
und in Reaktion auf UIApplicationWillEnterForegroundNotification
nennen startAnimation
.
- (void)startAnimation
{
if ([[self.layer animationKeys] count] == 0)
[self.layer addAnimation:a forKey:@"position"];
CFTimeInterval pausedTime = [self.layer timeOffset];
self.layer.speed = 1.0;
self.layer.timeOffset = 0.0;
self.layer.beginTime = 0.0;
CFTimeInterval timeSincePause =
[self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
self.layer.beginTime = timeSincePause;
}
- (void)stopAnimation
{
CFTimeInterval pausedTime =
[self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
self.layer.speed = 0.0;
self.layer.timeOffset = pausedTime;
}
Das problem ist, dass es fängt wieder am Anfang und es ist hässlich Sprung von der letzten position, wie gesehen, auf app snapshot das system hat bei der Anwendung hat Sie die EINGABETASTE hintergrund zurück an den Anfang der Schleife animation.
Ich kann nicht herausfinden, wie man es zu Beginn an letzter Stelle, wenn ich wieder zu-fügen Sie die animation. Ehrlich gesagt, ich verstehe einfach nicht, wie dieser code aus QA1673 funktioniert: resumeLayer
es setzt die Ebene.beginTime zweimal, das scheint überflüssig. Aber wenn ich schon entfernt, den ersten Satz zu null, es nicht wieder die animation, wo er unterbrochen wurde. Getestet wurde dies mit einfachen tap-gesten-Erkennung, das hat toggle-animation - das ist nicht unbedingt in Bezug auf meine Probleme mit dem wiederherstellen aus dem hintergrund.
Welchem Zustand sollte ich mich erinnern, bevor die animation wird entfernt und wie kann ich wieder die animation aus, dass der Staat, wenn ich wieder später hinzufügen?
InformationsquelleAutor der Frage Palimondo | 2011-09-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nach ganz viel recherche und Gespräche mit der iOS-Entwicklung-gurus, es scheint, dass QA1673 hilft nicht, wenn es um das innehalten, backgrounding, dann verschieben in den Vordergrund zu stellen. Mein Experiment zeigt auch, dass die delegate-Methoden, die das Feuer aus von Animationen, wie
animationDidStop
unzuverlässig werden.Manchmal Feuer, manchmal Sie nicht.
Dies schafft eine Menge Probleme, weil es bedeutet, dass, nicht nur sind Sie auf der Suche an einem anderen Bildschirm, auf dem Sie waren, als Sie angehalten haben, aber auch die Abfolge der Ereignisse, die sich aktuell in der Bewegung unterbrochen werden kann.
Meine Lösung war bisher wie folgt:
Wenn die animation gestartet wird, bekomme ich den start-Zeit:
mStartTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
Wenn der Benutzer trifft die pause-Taste, Entferne ich die animation von der
CALayer
:[layer removeAnimationForKey:key];
Bekomme ich die absolute Zeit mit
CACurrentMediaTime()
:CFTimeInterval stopTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
Mithilfe der
mStartTime
undstopTime
berechne ich eine offset-Zeit:Ich auch die Modell-Werte des Objekts, die von der
presentationLayer
. So, meinestop
Methode sieht wie folgt aus:Auf fortsetzen, ich nachrechnen was übrig bleibt für die Pausen-animation basierend auf der
mTimeOffset
. Das ist ein bisschen chaotisch, denn ich bin mitCAKeyframeAnimation
. Ich herausfinden, was keyframes sind hervorragend basiert auf dermTimeOffset
. Auch habe ich berücksichtigt, dass die pause eventuell aufgetreten mittleren Rahmen, z.B. auf halbem Weg zwischenf1
undf2
. Diese Zeit wird abgezogen von der Zeit, die keyframe.Ich fügen Sie dann diese animation auf der Ebene von neuem:
[layer addAnimation:animationGroup forKey:key];
Die andere Sache zu erinnern ist, dass Sie brauchen, um zu überprüfen, die fahne in der
animationDidStop
und entfernen Sie nur die animierte Ebene von der Eltern-mitremoveFromSuperlayer
wenn das flagYES
. Das bedeutet, dass die Ebene ist noch sichtbar, während der pause.Diese Methode scheint sehr mühsam. Es funktioniert aber! Ich würde lieben im Stande zu sein, einfach das zu tun dieses mit QA1673. Aber im moment für backgrounding, es funktioniert nicht, und dies scheint die einzige Lösung.
InformationsquelleAutor der Antwort Max MacLeod
Hey, ich hatte stolperte über die gleiche Sache in meinem Spiel, und schließlich finden eine etwas andere Lösung, als Sie, die Sie möglicherweise mögen 🙂 ich dachte, ich würde teilen die Abhilfe, die ich gefunden...
Meinem Fall ist mit UIView/UIImageView Animationen, aber es ist im Grunde immer noch CAAnimations im Kern... Der Kern meiner Methode ist, dass ich kopieren/speichern der aktuellen animation auf einen Blick, und lassen Sie dann Apple pausieren/fortsetzen der Arbeit noch, aber vor der Wiederaufnahme füge ich meiner animation wieder auf. So lassen Sie mich ein ganz einfaches Beispiel:
Sagen wir, ich habe eine UIView genannt movingView. Die UIView - center animiert über den standard [UIView animateWithDuration...] nennen. Mit den genannten QA1673 code, es funktioniert großartig, anhalten/fortsetzen (bei verlassen der app)... aber egal, ich merkte bald, dass beim beenden, ob ich anhalten oder nicht, die animation wurde komplett entfernt... und hier war ich in Ihrer position.
Also mit diesem Beispiel, hier ist, was ich getan habe:
Wenn die app beendet, um hintergrund, dass ich dies tun:
Nun in meinem UIApplicationWillEnterForegroundnotification handler:
Und das ist ziemlich viel! Es hat bei mir geklappt so weit 🙂
Können Sie ganz einfach verlängern es mehr Animationen oder Ansichten nur wiederholen diese Schritte für jede animation. Es funktioniert sogar für das unterbrechen/wiederaufnehmen der UIImageView-Animationen, also die standard - [Bildansicht startAnimating]. Die Ebene animation-Schlüssel für die (übrigens) ist "Inhalt".
Liste 1) Anhalten und Fortsetzen von Animationen.
InformationsquelleAutor der Antwort cclogg
Es ist überraschend zu sehen, dass dies nicht mehr einfach. Ich erstellte eine Kategorie, basierend auf cclogg Ansatz, das sollte sich machen dies zu einem one-liner.
CALayer+MBAnimationPersistence
Einfach aufrufen
MB_setCurrentAnimationsPersistent
auf Ihrer Ebene nach dem einrichten des gewünschten Animationen.Oder geben Sie die Animationen, die beibehalten werden sollte ausdrücklich.
InformationsquelleAutor der Antwort Matej Bukovinski
Kann ich nicht kommentieren, so will ich hinzufügen, es als Antwort.
Ich verwendet cclogg die Lösung, aber meine app stürzt ab, wenn die animation die Sicht war entfernt von seinem superview, wieder Hinzugefügt, und werde dann in den hintergrund.
Die animation wurde unendlich durch Einstellung
animation.repeatCount
zuFloat.infinity
.Die Lösung, die ich hatte, war zu setzen
animation.removedOnCompletion
zufalse
.Es ist sehr komisch, dass es funktioniert, weil die animation ist nie abgeschlossen. Hat jemand eine Erklärung, ich mag es zu hören.
Noch ein Tipp: Wenn Sie entfernen die Aussicht von seinem superview. Vergessen Sie nicht, entfernen Sie die Beobachter durch den Aufruf
NSNotificationCenter.defaultCenter().removeObserver(...)
.InformationsquelleAutor der Antwort Pepijn
Nur für den Fall, jemand braucht eine Swift 3 Lösung für dieses problem:
Alles, was Sie tun müssen, ist, um eine Unterklasse das animierte Ansicht von dieser Klasse.
Es ist immer anhalten und wieder alle Animationen auf, es ist Schicht.
Auf Gist:
https://gist.github.com/grzegorzkrukowski/a5ed8b38bec548f9620bb95665c06128
InformationsquelleAutor der Antwort Grzegorz Krukowski
War ich in der Lage, zur Wiederherstellung der animation (aber nicht die animation-position) speichern Sie eine Kopie der aktuellen animation und das hinzufügen es wieder auf fortsetzen. Ich rief startAnimation beim laden und beim betreten der Vorder-und pause bei der Eingabe der hintergrund.
InformationsquelleAutor der Antwort Warpling
Benutze ich cclogg Lösung mit großer Wirkung. Ich wollte auch noch einige zusätzliche Infos, die vielleicht jemand anderes helfen, weil es frustriert mich für eine Weile.
In meiner app habe ich eine Reihe von Animationen, einige, die Schleife für immer, einige, die nur einmal ausgeführt und erzeugt nach dem Zufallsprinzip. cclogg Lösung für mich gearbeitet, aber wenn ich noch ein paar code
um etwas zu tun, wenn nur das one-time-Animationen fertig waren, diesen code auslösen würde, wenn ich wieder meine app (mit cclogg Lösung), wenn diese bestimmte, einmalige Animationen, die ausgeführt wurden, wenn es angehalten wurde. Also habe ich ein flag (eine member-variable der meine benutzerdefinierte Klasse UIImageView) und setzen Sie es JA in die Rubrik, wo du wieder alle layer-Animationen (
resumeLayer
im cclogg ist, Analog zu Apple-Lösung QA1673), um dies zu halten. Ich mache dies für jeden UIImageView, ist die Wiederaufnahme. Dann, in deranimationDidStop
Methode, nur das one-time-animation-handling-code, wenn das flag NICHT. Wenn es JA, ignorieren den code. Schalten Sie die Flagge zurück um KEIN entweder-Weg. So, wenn die animation wirklich abgeschlossen ist, werden Ihre code ausgeführt wird. So wie diese:Hoffe, dass jemand hilft.
InformationsquelleAutor der Antwort BTGunner
Schreibe ich eine Swift 4 version-Erweiterung basierend auf dem @cclogg und @Matej Bukovinski Antworten. Alles, was Sie brauchen, ist zu nennen
layer.makeAnimationsPersistent()
Voll Kernaussage hier: CALayer+AnimationPlayback.swift, CALayer+PersistentAnimations.swift
Core-Teil:
InformationsquelleAutor der Antwort ArtFeel