UIView animateKeyframesWithDuration vs standard-animation-block-animation unterscheiden
Vor kurzem fand ich einige UIView animation-code und bemerkt, dass es nicht mit der animateKeyframesWithDuration:delay:options:animations:completion:
Methode richtig und habe seither versucht, es zu beheben, aber aus irgendeinem Grund die Animationen sind nicht identisch.
Hier ist der code, den ich gefunden habe:
view.transform = CGAffineTransformMakeTranslation(300, 0);
[UIView animateKeyframesWithDuration:duration/4 delay:delay options:0 animations:^{
//End
view.transform = CGAffineTransformMakeTranslation(-10, 0);
} completion:^(BOOL finished) {
[UIView animateKeyframesWithDuration:duration/4 delay:0 options:0 animations:^{
//End
view.transform = CGAffineTransformMakeTranslation(5, 0);
} completion:^(BOOL finished) {
[UIView animateKeyframesWithDuration:duration/4 delay:0 options:0 animations:^{
//End
view.transform = CGAffineTransformMakeTranslation(-2, 0);
} completion:^(BOOL finished) {
[UIView animateKeyframesWithDuration:duration/4 delay:0 options:0 animations:^{
//End
view.transform = CGAffineTransformMakeTranslation(0, 0);
} completion:^(BOOL finished) {
}];
}];
}];
}];
Gibt es zwei Probleme:
- Sollte man wirklich ein key-frame-animation anstelle von Schachtelung von Animationen innerhalb der completion-block.
- Bei der Verwendung
animateKeyframesWithDuration:delay:options:animations:completion:
Sie nennen soll dieaddKeyframeWithRelativeStartTime:relativeDuration:animations:
- Methode innerhalb der animation block. Wenn Sie nicht diese Methode aufrufen, dann ist diese Methode verhält sich wie ein standard-UIView animation-block.
Siehe Apple Dokumentation zu dieser Methode hier.
So, ich habe versucht, dieses Problem zu beheben, nutzen Sie die Methode korrekt:
view.transform = CGAffineTransformMakeTranslation(300, 0);
double frameDuration = 1.0/4.0; //4 = number of keyframes
[UIView animateKeyframesWithDuration:duration delay:delay options:0 animations:^{
[UIView addKeyframeWithRelativeStartTime:0*frameDuration relativeDuration:frameDuration animations:^{
view.transform = CGAffineTransformMakeTranslation(-10, 0);
}];
[UIView addKeyframeWithRelativeStartTime:1*frameDuration relativeDuration:frameDuration animations:^{
view.transform = CGAffineTransformMakeTranslation(5, 0);
}];
[UIView addKeyframeWithRelativeStartTime:2*frameDuration relativeDuration:frameDuration animations:^{
view.transform = CGAffineTransformMakeTranslation(-2, 0);
}];
[UIView addKeyframeWithRelativeStartTime:3*frameDuration relativeDuration:frameDuration animations:^{
view.transform = CGAffineTransformMakeTranslation(0, 0);
}];
} completion:nil];
Fühle ich mich wie die beiden Animationen sollen identisch sein, aber Sie sind es nicht. Was habe ich falsch gemacht in meinem Versuch?
Edit: Beispiel-Projekt (Verwenden Sie Befehl + T Umschalten langsame Animationen im simulator)
- "allerdings sind Sie nicht." können Sie das noch näher erläutern? Wie unterscheiden Sie sich?
- Tut mir Leid, ich sollte wirklich Hinzugefügt haben, ein Beispiel-Projekt, das habe ich nun Hinzugefügt. Das timing der keyframes einfach nicht passen. Auch: wow, David Rönnqvist! Ihre Löschen* Animation Code post ist der Grund, warum ich gepostet diese Frage!
Du musst angemeldet sein, um einen Kommentar abzugeben.
tl;dr: Sie sehen wahrscheinlich anders, weil Sie verschiedene Dinge tun und dazu führen, dass verschiedene Animationen Hinzugefügt, um die zwei Ansichten. Leider habe ich nicht wirklich wissen, wie es zu lösen ist.
Was passiert hinter der ersten version
Als Sie haben schon gesagt, die erste version nicht mit der API korrekt. Es doesn ' T fügen Sie keyframes mit
addKeyframeWithRelativeStartTime:relativeDuration:animations:
sondern ändert die Eigenschaften direkt in der animation block. Dann erstellt es eine neue "key frame animation" (Sie werden bald sehen, warum ich verwendet, erschrecken Zitate dort) in den Abschluss-block.Hinter die kulissen dieser nicht tatsächlich
CAKeyframeAnimations
(obwohl ich nicht glaube, sollten Sie sich auf diese Tatsache). Dies ist eine Protokollierung, dass ich von der vier-animation von Objekten, die Hinzugefügt werden, um die Ebene hinterview1
in Ihrem Projekt. (Ich betrogen ein wenig und nur protokolliert, die.m41
Teil der Transformation (das entspricht translation entlang x)).Wie Sie sehen können, jede animation hat eine
fromValue
aber wedertoValue
oderbyValue
. Wie, Lesen Sie in der Dokumentation, dies bedeutet:Was passiert hinter der zweiten version
Auf der anderen Seite, die zweite version, die korrekt ergänzt keyframes für die animation der Ergebnisse in diesem einzigen CAKeyframeAnimation Hinzugefügt werden, um die Ebene hinter
view2
. (Ich bin immer noch nur die Protokollierung der.m41
Teil der Transformation)Wie Sie sehen können, es bewegt sich, zwischen die selben Werte mit den gleichen Zeiten, aber in einem einzelnen key-frame-animation. Es hat auch die gleiche Gesamtdauer und verwendet die gleichen timing-Funktion.
Es ist eine Sache, die ich bin nicht zu verstehen. Wenn ich ändern Sie die echte key-frame-animation (in meinem überschrieben
addAnimation:forKey:
vor dem Aufruf von super), um explizit festzulegen, die die timing-Funktion in das array von timing-Funktionen, dann tun Sie genau gleich Aussehen. Das heißt, ich tun dies, um die keyframe-animation, bevor Sie der Ebene Hinzugefügt wird.Dieser trick ist super hässlich, und Sie sollten nie verwenden es für andere Dinge als das Reine debugging!
Warum also tun Sie anders Aussehen?
Gut, ich denke, die Antwort hat zu tun mit dem timing-Funktionen, array der keyframe-animation, UIKit erstellt, im zweiten Fall. Das ist so ziemlich die einzige Schlussfolgerung, die ich hatte.
Sagte, ich weiß nicht, ob das ein bug ist oder wie es zu lösen ist. Ich weiß nur, was Sie den code in Ihr Projekt tatsächlich auf die Core-Animation-Ebene.
timingFunctions
leer. Es setzttimingFunction
- und das ist es. Es gibt keine API (ab iOS 9) auf UIKit Seite. Für nun, habe ich diese kleine Erweiterung, die es erlaubt, zu passentimingFunction
undtimingFunctions
nach der Tat: github.com/salutis/View-KeyframeAnimationCurve