7

NSViewコアアニメーションを使用してスライドしようとしています。のようなものに頼るのではなく、明示的なアニメーションを使用する必要があると思います[[view animator] setFrame:newFrame]。これは主に、アニメーションの終了後にアクションを実行するためにアニメーションデリゲートを設定する必要があるためです。

アニメーターを使用して問題なく動作していますが、前述したように、アニメーションが終了したときに通知を受ける必要があります。私のコードは現在次のようになっています:

// Animate the controlView
NSRect viewRect = [controlView frame];
NSPoint startingPoint = viewRect.origin;
NSPoint endingPoint = startingPoint;
endingPoint.x += viewRect.size.width;
[[controlView layer] setPosition:NSPointToCGPoint(endingPoint)];

CABasicAnimation *controlPosAnim = [CABasicAnimation animationWithKeyPath:@"position"];
[controlPosAnim setFromValue:[NSValue valueWithPoint:startingPoint]];
[controlPosAnim setToValue:[NSValue valueWithPoint:endingPoint]];
[controlPosAnim setDelegate:self];
[[controlView layer] addAnimation:controlPosAnim forKey:@"controlViewPosition"];

これは視覚的には機能しますが(最後に通知が届きます)、実際のcontrolViewは移動しないようです。ウィンドウを更新すると、controlViewが消えます。交換してみました

[[controlView layer] setPosition:NSPointToCGPoint(endingPoint)];

[controlView setFrame:newFrame];

これにより、ビュー(およびレイヤー)が移動しますが、何かが破損しているため、アプリがすぐにセグメンテーション違反で停止します。

明示的なアニメーションの例のほとんどは、を動かしているだけのようですCALayer。を移動しNSView、代理人を設定できる方法が必要です。どんな助けでもいただければ幸いです。

4

2 に答える 2

8

ビューに加えられた変更は、現在の実行ループの終了時に有効になります。レイヤーに適用されるアニメーションについても同じことが言えます。

ビューのレイヤーをアニメーション化する場合、ビュー自体は影響を受けません。そのため、アニメーションが完了すると、ビューは元の位置にジャンプして戻るように見えます。

これらの2つのことを念頭に置いて、アニメーションが完了したときにビューのフレームを希望のフレームに設定し、ビューのレイヤーに明示的なアニメーションを追加することで、希望の効果を得ることができます。

アニメーションが開始されると、ビューが開始位置に移動し、終了位置にアニメーション化されます。アニメーションが完了すると、ビューには指定したフレームが表示されます。

- (IBAction)animateTheView:(id)sender
{
    // Calculate start and end points.  
    NSPoint startPoint = theView.frame.origin;
    NSPoint endPoint = <Some other point>;    

    // We can set the frame here because the changes we make aren't actually
    // visible until this pass through the run loop is done.
    // Furthermore, this change to the view's frame won't be visible until
    // after the animation below is finished.
    NSRect frame = theView.frame;
    frame.origin = endPoint;
    theView.frame = frame;

    // Add explicit animation from start point to end point.
    // Again, the animation doesn't start immediately. It starts when this
    // pass through the run loop is done.
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    [animation setFromValue:[NSValue valueWithPoint:startPoint]];
    [animation setToValue:[NSValue valueWithPoint:endPoint]];
    // Set any other properties you want, such as the delegate.
    [theView.layer addAnimation:animation forKey:@"position"];
}

もちろん、このコードが機能するには、ビューとそのスーパービューの両方にレイヤーがあることを確認する必要があります。スーパービューにレイヤーがない場合、グラフィックが破損します。

于 2012-02-17T19:24:38.537 に答える
5

最後に(アニメーションを設定した後)setPositionを呼び出す必要があると思います。また、ビューのレイヤーを明示的にアニメーション化する必要はないと思います。代わりに、アニメーターを使用してアニメーションを設定することにより、ビュー自体をアニメーション化する必要があります。アニメーターでデリゲートを使用することもできます:)

// create controlPosAnim
[controlView setAnimations:[NSDictionary dictionaryWithObjectsAndKeys:controlPosAnim, @"frameOrigin", nil]];
[[controlView animator] setFrame:newFrame];
于 2011-05-19T22:37:35.060 に答える