3

In a UIView subclass, I have this method:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch * aTouch = [touches anyObject];
    CGPoint loc = [aTouch locationInView:self];

    CALayer * layer = [CALayer layer];
    [layer setBackgroundColor: [[UIColor colorWithHue:(float)rand()/RAND_MAX saturation:1 brightness:1 alpha:1] CGColor]];
    [layer setFrame:CGRectMake(0, 0, 64, 64)];
    [layer setCornerRadius:7];
    [layer setPosition:loc];

    [layer setOpacity:0];

    [self.layer addSublayer:layer];


    CABasicAnimation * opacityAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    opacityAnim.duration=2.42;
    opacityAnim.fromValue=[NSNumber numberWithFloat:0];
    opacityAnim.toValue=  [NSNumber numberWithFloat:1];
    opacityAnim.fillMode = kCAFillModeForwards;
    opacityAnim.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    opacityAnim.removedOnCompletion=NO;
    opacityAnim.delegate=self;

//  explicit animation is working as expected
//  [layer addAnimation:opacityAnim forKey:@"opacityAnimation"];

//     Why isn't the implicit animation working ?
[layer setOpacity:1];
}

What am I missing ? I expect the CALayer layer's opacity to be implicitly animated with the last line in this method.

My solution

Here is how I solved the problem thanks to Duncan's answer.

-(CALayer *) layerFactory:(CGPoint) loc {
    CALayer * layer = [CALayer layer];
    [layer setBackgroundColor: [[UIColor colorWithHue:(float)rand()/RAND_MAX saturation:1 brightness:1 alpha:1] CGColor]];
    [layer setFrame:CGRectMake(0, 0, 64, 64)];
    [layer setCornerRadius:7];
    [layer setPosition:loc];
    [layer setOpacity:0];
    return layer;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch * aTouch = [touches anyObject];
    CGPoint loc = [aTouch locationInView:self];


    [CATransaction begin];
    CALayer * layer = [self layerFactory:loc];
    [self.layer addSublayer:layer];
    [CATransaction commit];


    [CATransaction begin];
    [CATransaction setAnimationDuration:0.45];
    [layer setOpacity:1];
    [CATransaction commit];

}

You only need to put the creation of the layer, and the modifiction of the opacity in two different CATransaction blocks. However, moving the creation (not the adding) of the layer to the layerFactory method changes nothing to the situation.

I don't know whether it's the best solution, but it's working.

4

1 回答 1

4

您不能创建图层并设置其不透明度,然后以相同的方法将不透明度设置为新值并获得隐式动画。尝试将您的创建/配置层代码放在 CATransaction 开始/结束块中,然后将不透明度设置为 1 的代码放在另一个事务开始/结束块中。

我认为这会奏效,但必须尝试才能确定。

如果这不起作用,请调用代码以使用 performSelector:withObject:afterDelay 和延迟值 0 将不透明度设置为 1。这将使系统添加不透明度为 0 的图层,然后将不透明度更改为1 作为单独的交易。

于 2013-03-20T13:40:36.320 回答