14
  • XCode で簡単なプロジェクトを作成する
  • マルチタッチ イベントを受け取るようにビューを設定する
  • touchesBegan で応答し、タッチ イベントを検出すると CALayer を作成します
  • CALayer の不透明フェードアウト アニメーションを作成する
  • アニメーションが停止したら、親から CALayer を削除します

期待: CALayer が正常に消える

実際: 消える前に CALayer フラッシュ (点滅)

完全なソース コード:

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.view.multipleTouchEnabled = YES;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    for (UITouch* touch in touches) {
        CGPoint p = [touch locationInView:self.view];

        //NSLog(@"touch=%@ p=%@", touch, NSStringFromCGPoint(p));

        CALayer *layer = [CALayer layer];
        layer.position = p;
        layer.bounds = CGRectMake(0, 0, 70, 70);
        layer.cornerRadius = 30;
        layer.masksToBounds = NO;
        layer.backgroundColor = [UIColor colorWithRed:102.0/255.0 green:156.0/255.0 blue:255.0/255.0 alpha:0.8].CGColor;
        layer.shouldRasterize = YES;

        CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
        fadeOutAnimation.fromValue = [NSNumber numberWithFloat:1.0];
        fadeOutAnimation.toValue = [NSNumber numberWithFloat:0.0];
        fadeOutAnimation.duration = 0.5;
        fadeOutAnimation.delegate = self;
        fadeOutAnimation.removedOnCompletion = NO;
        [fadeOutAnimation setValue:layer forKey:@"parentLayer"];
        [layer addAnimation:fadeOutAnimation forKey:@"opacity"];

        [self.view.layer addSublayer:layer];
    }
}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
    if(flag) {
        CALayer *layer = [theAnimation valueForKey:@"parentLayer"];
        if(layer) {
            layer.opaque = NO;
            layer.opacity = 0.0;
            //layer.hidden = YES;
            //NSLog(@"The layer object was: %@ (%@)", layer, [layer name]);
            [layer removeFromSuperlayer];
            [layer removeAllAnimations];
        }
    }
}

@end
4

1 に答える 1

17

tl; dr:fillModeアニメーションをレイヤーに追加する前に、アニメーションのをに設定するkCAFillModeForwardsか、値を最終値に変更します。


基本的なアニメーションは、アニメーション期間中の視覚的なアニメーションのみであり、実際の値は変更されません。完了時にアニメーションが削除されないように設定すると、レイヤーは引き続きアニメーションオブジェクトをアニメーションの1つとして参照します。ただし、すでにアニメーションを実行しています。

アニメーションのデフォルトの動作(塗りつぶしモード)はkCAFillModeRemoved、アニメーションの継続時間の直後に、アニメーションが発生しなかったかのようにレイヤーが表示されることを意味します。塗りつぶしモードをいずれかに変更するかkCAFillModeForwardskCAFillModeBothレイヤーをアニメーションの終了状態のままであるかのように見せることができます。

でアニメーションの開始時に同じことを行うことができますが、kCAFillModeBackwardsほとんどの場合、アニメーションの開始時間を設定したときに適用されます。

したがって、アニメーションをアニメーションの最終状態のように見せるために、塗りつぶしモードを設定して...Forwardsアニメーションを削除しないか、レイヤーの実際の値を、追加する直前の予想値に変更することができます。ビューへのアニメーション。これにより、値が変更され、古い値から新しい値にアニメーション化されます。

于 2012-05-16T07:59:58.040 に答える