2017-05-12 3 views
0

arbeiten habe ich einen Fortschritt Methode here:CABasicAnimation auf CAShapeLayer nicht für Pfadänderung

func progress(incremented : CGFloat){ 
    if incremented <= self.bounds.width{ 
     self.progressLayer.removeFromSuperlayer() 
     let originBezierPathProg = UIBezierPath(roundedRect: CGRect(x:0, y:0, width:0, height:self.bounds.height) , cornerRadius: self.viewCornerRadius) 
     originBezierPathProg.close() 

     let newBezierPathProg = UIBezierPath(roundedRect: CGRect(x:0, y:0, width:incremented, height:self.bounds.height) , cornerRadius: self.viewCornerRadius) 
     bezierPathProg.close() 

     self.progressLayer.path = originBezierPathProg.cgPath 
     self.borderLayer.addSublayer(self.progressLayer) 

     let animation = CABasicAnimation(keyPath: "path") 
     animation.fromValue = originBezierPathProg.cgPath 
     animation.toValue = newBezierPathProg.cgPath 
     animation.duration = 1 
     self.progressLayer.add(animation, forKey: animation.keyPath) 

     self.progressLayer.path = newBezierPathProg.cgPath 
    } 
} 

Ich versuche, Fortschrittsbalken Fortschritt in einer animierten Weise zu machen. Aber wenn ich progress(100) rufe, rendern einfach die Leiste ohne Animation.

Wie kann ich es beheben?

Aktualisierung: Erstellt MCVE nach Robs Vorschlag: https://github.com/utkarsh2012/ProgressBarTest. Ich erwarte, dass die Fortschrittsbalken von width = 0 bis width = x (etwa 60)

sehen ähnlich aus wie dieses Problem CABasicAnimation with CALayer path doesn't animate

+0

Während dies [könnte etwas gestrafft werden] (https://gist.github.com/robertmryan/eb8a9a422ad3820e3eb20fe143be3893), funktioniert es für mich, wie es ist. Das Problem ist also entweder, wie Sie es aufrufen (zu früh, zu häufig, aus dem Hintergrundthread), oder Ihre 'Grenzen' oder 'inkrementierten' Werte sind so, dass die 'if'-Anweisung fehlschlägt.Wir brauchen ein ausführbares Beispiel für das Problem. – Rob

+0

Lassen Sie mich mit einem einfachen Projekt mit diesem Problem kommen. Habe jetzt schon seit einigen Stunden damit zu kämpfen, ich denke, das wirkliche Problem ist, dass es von einem UIViews var ididSet aufgerufen wird (und wahrscheinlich zu früh?). Ich mache auch Layout wenn nötig danach. Blick auf SetupView: https://github.com/TwoPence/TwoPence/blob/milestone/TwoPence/MilestoneFutureView.swift – zengr

+0

Es ist schwer zu sagen. Da ist etwas nicht miteinander verbundenes Zeug, aber zur gleichen Zeit nicht genug, um das Problem zu reproduzieren, denke ich. Wenn Sie möchten, dass wir Ihnen helfen, benötigen wir [MCVE] (http://stackoverflow.com/help/mcve), d. H. Zeigen Sie uns, wie Sie ein leeres Projekt erstellen, fügen Sie die Mindestmenge an Code ein, die Ihr Problem manifestiert. Oder, wenn Sie das Problem selbst diagnostizieren möchten, fügen Sie Debugging-Code hinzu, der (a) überprüft, ob es im Haupt-Thread passiert; (b) dass "Grenzen" das ist, was Sie denken, wenn "Fortschritt (inkrementiert:)" aufgerufen wird; (c) welcher "inkrementierte" Wert war. – Rob

Antwort

1

Die progress Methode ursprünglich gezeigt in Ihrer Frage zu animieren ist in Ordnung. Das Problem ist, wie du es benutzt hast. Nachdem wir das gesagt haben, gehen wir durch den MCVE.

In your MCVE gab es ein paar Dinge, um die Animation zu verhindern, und zwar:

  1. Die progress Verfahren war wie folgt:

    func progress(incremented: CGFloat) { 
        if incremented <= bounds.width { 
         let toPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: incremented + 100, height: bounds.height), cornerRadius: viewCornerRadius) 
    
         progressLayer.path = toPath.cgPath 
         borderLayer.addSublayer(progressLayer) 
    
         let animation = CABasicAnimation(keyPath: "path") 
         animation.fromValue = self.progressLayer.path 
         animation.toValue = toPath.cgPath 
         animation.duration = 3 
         progressLayer.add(animation, forKey: animation.keyPath) 
        } 
    } 
    

    dass die path setzt der neue Pfad zu sein, und dann animieren von diesem zu dem neuen Pfad (dh animieren zu und von demselben Pfad). Also keine Animation.

    Speichern Sie den alten Pfad, bevor Sie den path in seinen neuen "Endstatus" ändern und die Animation initiieren. Verwenden Sie den gespeicherten Pfad als der Animation.

  2. Die value Eigenschaft rief layoutSubviews:

    var value: Int? { 
        didSet { 
         progress(value: value!) 
         self.layoutSubviews() 
        } 
    } 
    

    layoutSubviews() direkt nie nennen.

  3. Die View-Controller wurde wie folgt an:

    override func viewDidLoad() { 
        super.viewDidLoad() 
        // Do any additional setup after loading the view, typically from a nib. 
        let view = DetailView(frame: self.view.frame) 
        view.value = 60 
        self.containerView.addSubview(view) 
    } 
    

    Versuchen Sie nicht, Animationen in viewDidLoad zu starten. Das ist zu früh im Lebenszyklus der Ansicht. Verwenden Sie stattdessen viewDidAppear (oder was auch immer). Dies ist in viewDidLoad in der Regel zu früh in der Ansicht Lebenszyklus.

  4. Verwandte zu diesem viewDidLoad Code, ändern Sie die value der DetailView (die die Animation ausgelöst), bevor Sie es zu der Ansicht Hierarchie hinzugefügt haben.


die Updates hier https://github.com/robertmryan/ProgressBarTest sehen.

+0

Wow, danke! So viele Dinge liefen schief! Vielen Dank für die Github PR! Das nächste Mal, wenn Sie in SF sind, Kaffee auf mich :) – zengr

+1

Oder wenn du in LA bist, schau mich an. – Rob

+0

Die Animation funktionierte, aber jetzt verursacht es ein merkwürdiges Verhalten, bei dem Daten von den Standardwerten in den Etiketten zu den tatsächlichen Werten wechseln. http://imgur.com/a/zqn2o wahrscheinlich eine Follow-up-Frage, wenn ich nicht in der Lage bin, eine Lösung zu finden. – zengr

Verwandte Themen