Wie bewegt man einen CALayer sofort (ohne Animation)


79

Ich versuche, eine CALayerin einer iOS-App zu ziehen.

Sobald ich seine Positionseigenschaft ändere, versucht es, die neue Position zu animieren und flackert überall:

 layer.position = CGPointMake(x, y)

Wie kann ich mich CALayerssofort bewegen ? Ich kann mich anscheinend nicht mit der Core Animation API auseinandersetzen.


In Bezug auf diese extrem alte Qualitätssicherung ist das entscheidende Problem heute: stackoverflow.com/a/56980329/294884
Fattie

Antworten:


166

Sie möchten Ihren Anruf wie folgt abschließen:

[CATransaction begin]; 
[CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
layer.position = CGPointMake(x, y);
[CATransaction commit];

1
Das ist genau das. Ich habe nicht einmal an die CATransaction gedacht. Danke vielmals!
Mel

5
Ja, 6 ½ Jahre später. Immer noch hilfreich. : D
Fogmeister

1
iOS7 unterstützt neue Kurzschrift:[UIView performWithoutAnimation:<#^(void)actionsWithoutAnimation#>];
k06a

2
7 Jahre, 7 Monate und 17 Tage später: immer noch hilfreich. Vielen Dank!
Kanobius

1
Daumen hoch 9 Jahre später
nshuman

32

Swift 3-Erweiterung:

extension CALayer {
    class func performWithoutAnimation(_ actionsWithoutAnimation: () -> Void){
        CATransaction.begin()
        CATransaction.setValue(true, forKey: kCATransactionDisableActions)
        actionsWithoutAnimation()
        CATransaction.commit()
    }
}

Verwendung :

CALayer.performWithoutAnimation(){
    someLayer.position = newPosition
}

1
Es ist nützlich, das @noescapeAttribut zum Block hinzuzufügen , um zuzulassen (und deutlich zu machen), dass selfes im Block nicht benötigt wird
Andrew

22

Sie können auch die Komfortfunktion verwenden

[CATransaction setDisableActions:YES] 

auch.

Hinweis: Lesen Sie unbedingt die Kommentare von Yogev Shelly, um mögliche Fallstricke zu verstehen.


5
Wichtig, dies wirkt sich auf alle CALayer aus, sodass Sie Aktionen wieder aktivieren können, nachdem Sie fertig sind, dh [CATransaction setDisableActions: YES]
Yogev Shelly,

Verdammt, das hätte ich sagen sollen. Gut gerettet. Der Befehl deaktiviert Animationen, bis sie auf NO gesetzt sind oder bis die Kerngrafik-Animations-Engine einen Ausführungszyklus abgeschlossen hat. Ich bin mir nicht sicher, ob das das richtige Wort dafür ist: / Aber danke, dass du das für alle geklärt hast.
Biclops

14

Wie andere vorgeschlagen haben, können Sie verwenden CATransaction.
Das Problem tritt auf, weil CALayer eine implizite Standardanimationsdauer von 0,25 Sekunden hat.

Eine einfachere (meiner Meinung nach) Alternative dazu setDisableActionsist daher die Verwendung setAnimationDurationmit einem Wert von 0.0.

[CATransaction begin];
[CATransaction setAnimationDuration:0.0];
layer.position = CGPointMake(x, y);
[CATransaction commit];

Leicht zu merken, leicht zu verstehen, wenn Sie den Code erneut lesen, und einfacher zu tippen. Vielen Dank!
Herr T

2

Kombinieren Sie hier frühere Antworten für Swift 4, um die Animationsdauer deutlich zu machen ...

extension CALayer
{
    class func perform(withDuration duration: Double, actions: () -> Void) {
        CATransaction.begin()
        CATransaction.setAnimationDuration(duration)
        actions()
        CATransaction.commit()
    }
}

Verwendung...

CALayer.perform(withDuration: 0.0) {
            aLayer.frame = aFrame
        }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.