2014-07-10 14 views
12

In einer UIView-Animation für eine Ansicht können Sie ihre Unteransichten mit UIViewAnimationOptionLayoutSubviews im Optionsparameter [UIView animateWithDuration:delay:options:animations:completion:] animieren. Jedoch kann ich keinen Weg finden, es zu animieren, indem es seine Sublayer auslegt, wenn sie nicht die Rückschicht einer Ansicht sind; Sie würden einfach an ihren Platz springen, um den neuen Grenzen der Ansicht zu entsprechen. Da ich mit Layern und nicht mit Ansichten arbeite, scheint es, als müsste ich Core-Animation anstelle von UIView-Animation verwenden, aber ich weiß nicht, wie (und wann), dass die Layer-Animation mit der Ansicht übereinstimmt Animation.Wie animieren Sie die Sublayer der Ebene einer UIView während einer UIView-Animation?

Das ist meine grundlegende Frage. Lesen Sie mehr, wenn Sie die konkrete Sache, die ich erreichen möchte, wissen wollen.

Ich habe eine Ansicht mit einem gepunkteten Rahmen erstellt, indem ich einen CAShapeLayer zum Layer der Ansicht hinzufüge (siehe diese stackoverflow Frage: Dashed line border around UIView). Ich passe den Pfad des CAShapeLayers an die Grenzen der Ansicht in layoutSubviews an.

Dies funktioniert, aber es gibt ein kosmetisches Problem: Wenn die Begrenzungen der Ansicht in einer UIView-Animation (wie während der Drehung) animiert wird, springt die gepunktete Grenze zu den neuen Grenzen der Ansicht, statt sanft als Ansicht zu animieren animiert seine Grenzen. Das heißt, der rechte und der untere Teil des gepunkteten Rands bleiben nicht jeweils an den rechten und unteren Teil der Ansicht gebunden, wenn die Ansicht animiert. Wie kann ich den gepunkteten Rahmen vom CAShapeLayer animieren, während er die Grenzen animiert?

Was ich bisher zu tun eine CABasicAnimation zum CAShapeLayer angefügt wird:

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 

    self.borderLayer.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath; 
    self.borderLayer.frame = self.bounds; 

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; 
    [self.borderLayer addAnimation:pathAnimation forKey:nil]; 
} 

Dies macht die punktierte Grenze führen zu animieren, aber es hat nicht die richtige Dauer Zeitfunktion und Animation entsprechen die Ansichtsanimation. Manchmal möchten wir auch nicht, dass der gepunktete Rahmen animiert wird. Wenn die Ansicht zum ersten Mal Layout ausführt, sollte der Rahmen nicht von einem alten Pfad zum neuen korrekten Pfad animiert werden. Es sollte nur erscheinen.

Antwort

19

Sie könnten die Antwort bereits gefunden haben, aber ich habe auch vor kurzem ähnliche Probleme konfrontiert, seit es gelöst wurde, werde ich die Antwort posten.

In - layoutSubViews Methode können Sie aktuelle UIView Animation als Trägerschicht des CAAnimation mit - animationForKey: Verfahren erhalten. diese verwenden, können Sie implementieren - layoutSubviews wie:

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    // get current animation for bounds 
    CAAnimation *anim = [self.layer animationForKey:@"bounds"]; 

    [CATransaction begin]; 
    if(anim) { 
     // animating, apply same duration and timing function. 
     [CATransaction setAnimationDuration:anim.duration]; 
     [CATransaction setAnimationTimingFunction:anim.timingFunction]; 

     CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; 
     [self.borderLayer addAnimation:pathAnimation forKey:@"path"]; 
    } 
    else { 
     // not animating, we should disable implicit animations. 
     [CATransaction disableActions]; 
    } 

    self.borderLayer.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath; 
    self.borderLayer.frame = self.bounds; 
    [CATransaction commit]; 
} 
+4

ich die „Position“ Eigenschaft zu verwenden, hatte die animationForKey zu bekommen, aber davon abgesehen, dass es funktionierte für mich großartig! – Eric

+2

Danke, aber ich sollte erwähnen, dass dies mit der Animationsmethode nicht funktioniert [UIView animateWithDuration: usingSpringWithDamping: initialSpringVelocity: Optionen: Animationen: completion:] –

+1

@Eric Sie können auch 'bounds.size' verwenden. Ein kurzer Haltepunkt und die Überprüfung der Animation Keys sagt mir, dass es 3 laufende Animationen gibt ' –