2013-01-30 12 views
9

Ich versuche, die Animation der Deckkraft und Position der Ebene um 3 Sekunden mit SetBeginTime zu verzögern. Ich habe den Layer boxLayer aufgerufen. Die Animation läuft gut, aber während der ersten 3 Sekunden (die Ebene soll noch nicht angezeigt werden) wird die Ebene an ihrer endgültigen Position und Opazität angezeigt. Es sollte nicht. Gruppenanimation löst das Problem nicht. Könnte jemand helfen? Siehe Code unten:Versuchen CABasicAnimation Position und Deckkraft der Ebene um 3 Sekunden zu verzögern, aber

// Create an animation that will change the opacity of a layer 
CABasicAnimation *fader = [CABasicAnimation animationWithKeyPath:@"opacity"]; 


// It will last 1 second and will be delayed by 3 seconds 
[fader setDuration:1.0]; 
[fader setBeginTime:CACurrentMediaTime()+3.0]; 


// The layer's opacity will start at 0.0 (completely transparent) 
[fader setFromValue:[NSNumber numberWithFloat:startOpacity]]; 

// And the layer will end at 1.0 (completely opaque) 
[fader setToValue:[NSNumber numberWithFloat:endOpacity]]; 

// Add it to the layer 
[boxLayer addAnimation:fader forKey:@"BigFade"]; 

// Maintain opacity to 1.0 JUST TO MAKE SURE IT DOES NOT GO BACK TO ORIGINAL OPACITY 
[boxLayer setOpacity:endOpacity]; 


// Create an animation that will change the position of a layer 
CABasicAnimation *mover = [CABasicAnimation animationWithKeyPath:@"position"]; 

// It will last 1 second and will be delayed by 3 seconds 
[mover setDuration:1.0]; 
[mover setBeginTime:CACurrentMediaTime()+3.0]; 

// Setting starting position 
[mover setFromValue:[NSValue valueWithCGPoint:CGPointMake(startX, startY)]]; 

// Setting ending position 
[mover setToValue:[NSValue valueWithCGPoint:CGPointMake(endX, endY)]]; 

// Add it to the layer 
[boxLayer addAnimation:mover forKey:@"BigMove"]; 

// Maintain the end position at 400.0 450.0 OTHERWISE IT IS GOING BACK TO ORIGINAL POSITION 
[boxLayer setPosition:CGPointMake(endX, endY)]; 
+0

, wie etwa ein Verfahren wie die Herstellung [self perform: @selector (Methodenname) withobject: nil afterDelay: 3.0f]; oder mithilfe von sleep(); –

+0

Mein Problem ist nicht die verzögerte Animation, sondern die Tatsache, dass die Ebene angezeigt wird, bevor die verzögerte Animation startet. – Armand

Antwort

17

Das Problem ist, dass Sie die boxLayer Eigenschaften von position und von opacity ihre Endwerte sind einstellen. Sie müssen:

  1. Stellen Sie die boxLayer Eigenschaften auf ihre Startwerte, nicht ihr End-Wert (das ist, warum es in der Endposition/Undurchsichtigkeit Start ist ... in der Regel, wenn die Animation sofort beginnt, ist dies nicht ein Problem, aber weil Sie den Start verzögern, ist die Verwendung der Endpositionen problematisch);

  2. Für Ihre zwei Animationen, haben Sie removedOnCompletion-NO und fillMode zu kCAFillModeForwards (dies ist der richtige Weg, um es in die Ausgangsposition nach Abschluss von Rückgriff zurück zu halten) zu ändern.

So:

// Create an animation that will change the opacity of a layer 
CABasicAnimation *fader = [CABasicAnimation animationWithKeyPath:@"opacity"]; 

// It will last 1 second and will be delayed by 3 seconds 
[fader setDuration:1.0]; 
[fader setBeginTime:CACurrentMediaTime()+3.0]; 

// The layer's opacity will start at 0.0 (completely transparent) 
[fader setFromValue:[NSNumber numberWithFloat:startOpacity]]; 

// And the layer will end at 1.0 (completely opaque) 
[fader setToValue:[NSNumber numberWithFloat:endOpacity]]; 

// MAKE SURE IT DOESN'T CHANGE OPACITY BACK TO STARTING VALUE  
[fader setRemovedOnCompletion:NO]; 
[fader setFillMode:kCAFillModeForwards]; 

// Add it to the layer 
[boxLayer addAnimation:fader forKey:@"BigFade"]; 

// SET THE OPACITY TO THE STARTING VALUE 
[boxLayer setOpacity:startOpacity]; 

// Create an animation that will change the position of a layer 
CABasicAnimation *mover = [CABasicAnimation animationWithKeyPath:@"position"]; 

// It will last 1 second and will be delayed by 3 seconds 
[mover setDuration:1.0]; 
[mover setBeginTime:CACurrentMediaTime()+3.0]; 

// Setting starting position 
[mover setFromValue:[NSValue valueWithCGPoint:CGPointMake(startX, startY)]]; 

// Setting ending position 
[mover setToValue:[NSValue valueWithCGPoint:CGPointMake(endX, endY)]]; 

// MAKE SURE IT DOESN'T MOVE BACK TO STARTING POSITION 
[mover setRemovedOnCompletion:NO]; 
[mover setFillMode:kCAFillModeForwards]; 

// Add it to the layer 
[boxLayer addAnimation:mover forKey:@"BigMove"]; 

// SET THE POSITION TO THE STARTING POSITION 
[boxLayer setPosition:CGPointMake(startX, startY)]; 

Persönlich denke ich, Sie eine Menge Arbeit für etwas, das viel leichter mit blockbasierten Animation auf der Ansicht (für die Zwecke getan von dieser Demonstration nehme ich an, dass Ihr boxLayer ein CALayer für eine Kontrolle ist, die box genannt wird). Sie brauchen nicht Quartz 2D, entweder, wenn Sie es auf diese Weise tun:

box.alpha = startOpacity; 
box.frame = CGRectMake(startX, startY, box.frame.size.width, box.frame.size.height); 

[UIView animateWithDuration:1.0 
         delay:3.0 
        options:0 
       animations:^{ 
        box.alpha = endOpacity; 
        box.frame = CGRectMake(endX, endY, box.frame.size.width, box.frame.size.height); 
       } 
       completion:nil]; 
+1

Mein Problem ist nicht die verzögerte Animation an sich. Das funktioniert. Mein Problem ist, dass die zu animierende Ebene (bewegt und eingeblendet) 3 Sekunden vor der Animation erscheint. – Armand

+1

Ja. Genau wie du es Rob gesagt hast. Es ist "beginnt für 3 Sekunden sichtbar, und dann verschwindet und langsam wieder zurück und animiert in der nächsten Sekunde". Ich habe die Ebene vor dem von mir geposteten Block erstellt. Ich dachte, es wäre zu lange gewesen, um alles zu posten. Es ist so, als könnte ich entweder die Ebenenanimation verzögern, während sie für die ersten Sekunden angezeigt wird, oder ich kann die Anzeige der Ebene verzögern, während keine Animation stattfindet. Komisch. Ich verwende Methoden wie setBeginTime und Duration. Nicht automatisches Layout oder AnimateWithDuration. Irgendeine Idee? – Armand

+0

@ user1915931 Während ich denke, dass es viel einfacher ist, eine blockbasierte Animation der Ansichten zu verwenden, habe ich meine Antwort auch mit der 'CABasicAnimation' Antwort aktualisiert, wenn Sie die Ebenen animieren möchten. – Rob

0

Dieser Artikel erklärt auch, warum Sie nicht removedOnCompletion mit fillMode https://www.objc.io/issues/12-animations/animations-explained/

In meinem Fall nutzen sollte ich das bin Animieren Ebene einer Ansicht, die als Navigation dient, aber eine Bounce-Animation, die sich in dieser Ansicht befindet, verzögert; Ich brauche beide dieser Positionen aktualisiert auf der Ebene, da es entlassen und dann erneut gezeigt werden kann. removedOnCompletion verwendet, wird nicht der Wert der Schicht aktualisieren, sobald die Animation

Die Art und Weise vervollständigt ich sie aktualisieren zu tun ist, um die Schicht in einem CATransaction Abschluss Block

CATransaction.setCompletionBlock { 
    // update the layer value 
} 

CATransaction.begin() 

// setup and add your animation 

CATransaction.commit() 
0

Für beginTime verwenden, sollten Sie die notwendigen Konfiguration Ihres Animationsobjekt machen und set fillMode zu kCAFillModeBackwards wie

zoomAnimation.fillMode = kCAFillModeBackwards; 

das in Apple-Dokumentation gesagt:

Verwenden Sie die Eigenschaft beginTime, um die Startzeit einer Animation festzulegen. Normalerweise beginnen Animationen während des nächsten Aktualisierungszyklus. Sie können den Parameter beginTime verwenden, um die Startzeit der Animation um einige Sekunden zu verzögern. Die Methode, zwei Animationen miteinander zu verknüpfen, besteht darin, die Startzeit einer Animation so einzustellen, dass sie mit der Endzeit der anderen Animation übereinstimmt. Wenn Sie den Start einer Animation verzögern, möchten Sie möglicherweise auch die Eigenschaft fillMode auf kCAFillModeBackwards festlegen. Dieser Füllmodus bewirkt, dass der Layer den Startwert der Animation anzeigt, auch wenn das Ebenenobjekt im Ebenenbaum einen anderen Wert enthält. Ohne diesen Füllmodus würden Sie einen Sprung zum endgültigen Wert sehen, bevor die Animation ausgeführt wird. Andere Füllmodi sind ebenfalls verfügbar.

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/AdvancedAnimationTricks/AdvancedAnimationTricks.html#//apple_ref/doc/uid/TP40004514-CH8-SW2

Auch von Robs Frage:

Für Ihre zwei Animationen, haben Sie removedOnCompletion auf NO und fillMode zu kCAFillModeForwards ändern (dies der richtige Weg ist, damit er nicht zurückkehrt zurück zur ursprünglichen Position nach Abschluss).

Es ist eine Art umstrittenen Aussage, denn:

Sobald die Animation entfernt wird, wird die Präsentationsschicht auf die Werte der Modellschicht zurückfallen, und da wir noch nie, daß die Schicht des modifizierten Position erscheint unser Raumschiff genau dort, wo es angefangen hat. Es gibt zwei Möglichkeiten, dieses Problem zu beheben:

Der erste Ansatz besteht darin, die Eigenschaft direkt auf der Modellschicht zu aktualisieren. Dies ist der empfohlene Ansatz, da es die Animation vollständig optional macht.

Alternativ können Sie festlegen, dass die Animation in ihrem endgültigen Status verbleibt, indem Sie ihre fillMode-Eigenschaft auf kCAFillModeForwards festlegen und verhindern, dass sie automatisch entfernt wird, indem Sie removedOnCompletion auf NO setzen. Es ist jedoch eine gute Übung, die Modell- und Präsentationslayer synchron zu halten, so dass dieser Ansatz sorgfältig verwendet werden sollte .

Von https://www.objc.io/issues/12-animations/animations-explained/