web-dev-qa-db-ja.com

CALayerのアニメーション終了コールバック?

CALayerのアニメーションのコールバックがどこにあるのか(または何かあるのか)疑問に思っています。具体的には、フレーム、位置などの変更のような暗黙のアニメーションの場合、UIViewでは、次のようなことができます。

[UIView beginAnimations:@"SlideOut" context:nil];
[UIView setAnimationDuration:.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animateOut:finished:context:)];
CGRect frame = self.frame;
frame.Origin.y = 480;
self.frame = frame;
[UIView commitAnimations];

具体的には、setAnimationDidStopSelectorはCALayerのアニメーションに必要なものです。そのようなものはありますか?

TIA。

65
Jeffrey Forbes

私は自分の質問に答えました。次のようにCABasicAnimationを使用してアニメーションを追加する必要があります。

CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"frame"];
anim.fromValue = [NSValue valueWithCGRect:layer.frame];
anim.toValue = [NSValue valueWithCGRect:frame];
anim.delegate = self;
[layer addAnimation:anim forKey:@"frame"];

そしてデリゲートメソッドを実装しますanimationDidStop:finished:そして、あなたは行ってもいいはずです。この機能が存在することに感謝します! :D

58
Jeffrey Forbes

完了ブロックハンドラーを備えたCATransactionを使用できます。

[CATransaction begin];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
[pathAnimation setDuration:1];
[pathAnimation setFromValue:[NSNumber numberWithFloat:0.0f]];    
[pathAnimation setToValue:[NSNumber numberWithFloat:1.0f]];
[CATransaction setCompletionBlock:^{_lastPoint = _currentPoint; _currentPoint = CGPointMake(_lastPoint.x + _wormStepHorizontalValue, _wormStepVerticalValue);}];
[_pathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
[CATransaction commit];
123
bennythemink

フェードインフェードアウトを行うために、このゴミで4時間を無駄にした。コード内のコメントに注意してください。

   [CATransaction begin];
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    animation.duration = 0.3;
    animation.fromValue = [NSNumber numberWithFloat:0.0f];
    animation.toValue = [NSNumber numberWithFloat:1.0f];
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeBoth;
  ///  [box addAnimation:animation forKey:@"j"]; Animation will not work if added here. Need to add this only after the completion block.

    [CATransaction setCompletionBlock:^{

        CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"opacity"];
        animation2.duration = 0.3;
        animation2.beginTime = CACurrentMediaTime()+1;
        animation2.fromValue = [NSNumber numberWithFloat:1.0f];
        animation2.toValue = [NSNumber numberWithFloat:0.0f];
        animation2.removedOnCompletion = NO;
        animation2.fillMode = kCAFillModeBoth;
        [box addAnimation:animation2 forKey:@"k"];

    }];

    [box addAnimation:animation forKey:@"j"];

    [CATransaction commit];
49
user3077725

Swift 3.0 bennytheminkのソリューションに基づいた3.0の答えは次のとおりです。

    // Begin the transaction
    CATransaction.begin()
    let animation = CABasicAnimation(keyPath: "strokeEnd")
    animation.duration = duration //duration is the number of seconds
    animation.fromValue = 0
    animation.toValue = 1
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    circleLayer.strokeEnd = 1.0

    // Callback function
    CATransaction.setCompletionBlock { 
        print("end animation")
    }

    // Do the actual animation and commit the transaction
    circleLayer.add(animation, forKey: "animateCircle")
    CATransaction.commit() 
46
tdon

2018年に向けて...

簡単にできませんでした。

[weak self]を忘れないでください。そうしないとクラッシュします。

func animeExample() {

    CATransaction.begin()

    let a = CABasicAnimation(keyPath: "fillColor")
    a.fromValue, duration = ... etc etc

    CATransaction.setCompletionBlock{ [weak self] in
        self?.animeExample()
        self?.ringBell()
        print("again...")
    }

    someLayer.add(a, forKey: nil)
    CATransaction.commit()
}

。 。 。 。 。注-重要なヒント>>>>>

重要なヒントのためにこの投稿を中断します。

あなた[〜#〜] [〜#〜]にはsetCompletionBlock[〜#〜] before [〜#〜]行someLayer.add。

Googleで詳細を読むこともできますが、一般的にはこの順序で行うことが重要です。そして今、投稿に戻ります!

<<<<<注-重要なヒント。 。 。 。 。

この例では、再び自分自身を呼び出します。

もちろん、任意の関数を呼び出すことができます。


iOSアニメーションを初めて使用する場合の注意:

  1. 「_」は(forKeyのように)無関係で、めったに使用されないです。 nilに設定します。設定する場合は、「任意の文字列」に設定します。

  2. 「keyPath」は、実際には実際の「アニメーション化するもの」です。文字通りレイヤーのプロパティ "opacity"、 "backgroundColor"などのようなものですが、string 。 (単に「欲しいもの」を入力することはできません。レイヤーの実際のプロパティの名前である必要があり、アニメート可能でなければなりません。)

繰り返します:「キー」(めったに使用しない-単にnilに設定する)と「キーパス」はまったく関係ありません。

多くの場合、これら2つがconfused(愚かな名前のおかげ)であるコード例がありますが、これはあらゆる種類の問題を引き起こします。


別の方法として、デリゲートを使用することもできますが、(A)自己完結型でどこでも使用できるため、(B)通常複数のアニメがあるため、完了ブロックを使用する方がはるかに簡単です。デリゲートは退屈です。

40
Fattie

Googleでこのページを見つけた人への注意:アニメーションオブジェクトの「デリゲート」プロパティを通知を受け取るオブジェクトに設定し、そのオブジェクトの.mで「animationDidStop」メソッドを実装することで、本当に仕事を完了できます。ファイル。試してみたところ、うまくいきました。ジョー・ブローがそれが正しい方法ではないと言った理由はわかりません。

10
moonman239

Swift 4 +では、delegateを追加しました

class CircleView: UIView,CAAnimationDelegate {
...

let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.delegate = self//Set delegate

アニメーション完了コールバック-

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
     print("Animation END")
  }
10
Jack

Swift 5.

func blinkShadow(completion: @escaping (() -> Void)) {
    CATransaction.begin()
    let animation = CABasicAnimation(keyPath: "shadowRadius")
    animation.fromValue = layer.shadowRadius
    animation.toValue = 0.0
    animation.duration = 0.1
    animation.autoreverses = true
    CATransaction.setCompletionBlock(completion)
    layer.add(animation, forKey: nil)
    CATransaction.commit()
}
1
Jimmy_m

CATransactionをいじりたくない場合。アニメーションオブジェクトにコールバックをカプセル化する拡張機能を作成しました。

コードは次のスニペットにあります: https://gitlab.com/snippets/1786298

そして、次のように使用できます:

let appearAnimation = CASpringAnimation(keyPath: "transform")
appearAnimation.fromValue = contentView.layer.transform
appearAnimation.toValue = CATransform3DIdentity
appearAnimation.mass = 0.65
appearAnimation.duration = appearAnimation.settlingDuration
appearAnimation.isAdditive = true
appearAnimation.onCompletion {
    completed()
}
0
netigger

CAAnimationオブジェクトを設定するときに、特定のアニメーションの名前を設定できます。 animationDiStop:finishedでは、提供されたtheAnimationオブジェクトの名前を比較するだけで、アニメーションに基づいて特定の機能を実行できます。

0
JavaJoe