2016-06-20 7 views
9

Mein Problem ist, dass meine UIView-Animation nur nach dem ersten Mal funktioniert. Ich habe zwei verschiedene Animationen. Der erste Satz funktioniert korrekt, der zweite Satz gibt mir Probleme. Das erste Set verschiebt 4 Tasten etwas weiter auf den Bildschirm als dort, wo ich sie haben möchte. (Diese Orte nenne ich extendedState) Die zweite Reihe von Animationen schiebt sie ein wenig zurück zu der Position, die ich will. Dies gibt den Effekt, zurück zur richtigen Stelle zu springen.UIView Animation animiert nicht beim ersten Versuch

Zwischen den beiden Animationen gibt es eine kurze Sekunde, in der die Buttons wieder in die Ausgangsposition zurückblinken, sobald die ersten Animationen fertig sind. Indem Sie diese Startposition auf die extendedStates setzen (den Ort, an dem sie sich befinden, wenn sie aufhören zu animieren), scheinen sich die Buttons nicht zwischen Animationen zu bewegen (was gut ist. Das ist was ich will).

Hier ist die Reihenfolge der Operationen:

  1. ich eine Taste tippen, die den ersten Satz von Animationen starten
  2. Im animationDidStop Block (die perfekt funktioniert gut), ich den zweiten Satz von Animationen starten (dies ist derjenige, der auf dem ersten Versuch animieren)

Hier ist der Code für die Schaltfläche Handler nicht:

@IBAction func selectAnimal(sender: UIButton) { 

    showButtons() 
    bigCircle.enabled = false 
    enableButtons() 

    if(tapToSelectLabel.hidden) { 
     animator.repositionButtonsToExtendedState(buttons) //sets the starting position to the extendedState so it appears not to move between animations 
     animator.slideButtonsIntoScreen(buttons, delegate: self) //this is the first set of animations 

    } 

    if(sender.titleLabel != nil) { 

     if(bigCircleLabel.text != "Choose an animal") { 

      if let answer:String = bigCircleLabel.text { 
       solution = game.checkAnswer(answer, question: game.threeQuestions[game.questionIndex]) 
      } 

      showResponse() 
     } 
    } 
} 
Nun

hier ist der Code innerhalb des animationDidStop Block

let buttonRects:[CGRect] = [CGRectMake(834, 120, 175, 175), 
             CGRectMake(631, 198, 175, 175), 
             CGRectMake(470, 365, 175, 175), 
             CGRectMake(386, 578, 175, 175)] 

      UIView.animateWithDuration(0.35, delay: 0, options: [.BeginFromCurrentState, ], animations: { 
         self.buttons[3].frame = buttonRects[3] 
        }, completion: { (value:Bool) in 
         self.buttons[3].enabled = true 

         UIView.animateWithDuration(0.25, delay: 0, options: [ ], animations: { 
          self.buttons[2].frame = buttonRects[2] 
          }, completion: { (value:Bool) in 
           self.buttons[2].enabled = true 

           UIView.animateWithDuration(0.4, delay: 0, options: [ ], animations: { 
            self.buttons[1].frame = buttonRects[1] 
            }, completion: { (value:Bool) in 
             self.buttons[1].enabled = true 

             UIView.animateWithDuration(0.5, delay: 0, options: [ ], animations: { 
              self.buttons[0].frame = buttonRects[0] 
              }, completion: { (value:Bool) in 
               self.buttons[0].enabled = true 
             }) 
           }) 
         }) 
        }) 

^Dieser Code gleitet die Tasten ein wenig nach hinten zu der Stelle ich sie möchte sein.

Hier ist der Code für meine Animator Klasse

animator.slideButtonsIntoScreen

func slideButtonsIntoScreen(buttons:[UIButton], delegate:UIViewController) { 

    let center = CGPoint(x:delegate.view.frame.width, y:delegate.view.frame.height) 
    let startAngles:[CGFloat] = [0.405, 0.75, 1.1, 1.48] 
    let endAngles:[CGFloat] = [1.95, 2.25, 2.622, 2.98] 
    let radii:[CGFloat] = [555, 559, 558.5, 551] 
    let durations:[Double] = [1.75, 1.5, 1.25 , 1] 

    for index in 0...3 { 
     let path = UIBezierPath(arcCenter: center, radius: radii[index], startAngle: -startAngles[index], endAngle: -endAngles[index], clockwise: false) 
     let anim = CAKeyframeAnimation(keyPath: "position") 
     anim.path = path.CGPath 
     anim.rotationMode = kCAAlignmentNatural 
     anim.repeatCount = 0 
     anim.duration = durations[index] - 0.25 
     anim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) 
     anim.setValue("on", forKey: "type") 
     anim.delegate = delegate 
     buttons[index].layer.addAnimation(anim, forKey: "animate position along path"+String(index)) 
     anim.removedOnCompletion = true 

    } 

} 

animator.repositionButtonsToExtendedState

func repositionButtonsToExtendedState(buttons:[UIButton]) { 


    let buttonExtendedRects:[CGRect] = [CGRectMake(755, 155, 175, 175), 
             CGRectMake(585, 245, 175, 175), 
             CGRectMake(450, 405, 175, 175), 
             CGRectMake(393, 590, 175, 175)] 

    for index in 0...3 { 
     buttons[index].frame = buttonExtendedRects[index] 
    } 
} 

I Haltepunkte zu setzen und print-Anweisungen, damit ich weiß für eine Tatsache, dass es die Animation beim ersten Versuch erreicht, es funktioniert einfach nicht die Animation zeigen. Es funktioniert genau so, wie es jedes Mal nach dem ersten sein sollte.

+2

Ihr Code sieht aus wie überall. Bitte erstellen Sie ein leeres Projekt und fügen Sie ein [minimales, vollständiges und überprüfbares Beispiel] (http://stackoverflow.com/help/mcve) Ihres Problems hinzu. – JAL

+1

Wenn Sie AutoLayout verwenden, sollten Sie die Einschränkungen anstelle des Rahmens animieren. –

Antwort

1

Es ist in der Regel eine schlechte Idee, Frames bei Verwendung des automatischen Layouts zu ändern. Von dem, was es scheint, anstatt den Rahmen der Einstellung zu sein, wo die Animation stoppt, können Sie die Objekte gesetzt einfach nicht wieder in seine ursprüngliche Position zurückzusetzen, wenn es dies vervollständigt mit:

anim.fillMode = kCAFillModeForwards 
anim.removedOnCompletion = false 

aber sicher sein, diejenigen zu platzieren Linien, bevor Sie die Animation

buttons[index].layer.addAnimation(anim, forKey: "animate position along path"+String(index)) 

um zu vermeiden, die Einstellung der Rahmen wieder hinzufügen, wenn Sie Ihre Tasten wollen zurück bewegen, sollten Sie grundsätzlich die gleiche Animation tun, sondern statt

clockwise: false 

setzen es auf true

clockwise: true 

dann von dort aus Sie Ihre Endwinkel als neuer Startwinkel für die Bewegung zurück, und stellen Sie Ihre Endwinkel für die Bewegung dorthin zurück, wo Sie brauchen, um die Tasten

sein können
+0

Ja, das ist im Wesentlichen, was ich getan habe, um mein Problem zu lösen, danke für die Antwort, es ist eine gute Erklärung für jeden mit einem ähnlichen Problem –

5

Statt UIView.animate der mit den Tasten nach hinten in die richtige Stelle zu bewegen, habe ich nur ein weiteres UIBezierPath es rückwärts zu bewegen, auf dem gleichen Kreis.

Diese Lösung vermeidet die Notwendigkeit zu halten, um den Rahmen der Tasten Einstellung, die ich war die Wurzel aller meiner Probleme glauben - die widersprüchlichen Rahmen fixierende Aussagen.

0

Wenn Sie sie nur abprallen lassen möchten, können Sie UIView.animateWithDuration(_,delay:_, usingSpringWithDamping:_,initialSpringVelocity:_,options:_,animations_,completed:_) verwenden.

Aber das Problem in Ihrem Code ist, dass nur Ihre Root-Animation Optionen korrekt ist. nur die erste enthält [.BeginFromCurrentState], geben Sie diese Option auch für alle Ihre Animationen.

Außerdem können Sie Verzögerung als Option auch hier verwenden. Legen Sie Ihren zweiten Satz von Animationen nicht in den fertigen Block der ersten Animation, starten Sie sie nach einem delay.