尝试动画时,CALayer会立即移动吗?

时间:2010-07-22 18:55:57

标签: iphone animation core-animation core-graphics calayer

下面的代码处理一堆CALayers。每次将新图层推入堆栈时,该功能都会被锁定,并且所有现有图层都会在屏幕上向下移动,以便为新图层腾出空间。完成最后一层后,再次解锁该功能,以便可以推送新图层。

我的问题是,每次此代码在newLayer上运行初始动画时。换句话说,不是将新图层定位在CGPointMake(0, 0-offset),然后将其设置为CGPointMake(0, currentLayer.position.y + offset),而是立即显示在最终位置。我错过了什么吗?谢谢!

-(void)addNewLayerWithHeight:(float)layerHeight {
    if(!animationLocked) {
        animationLocked = YES;
        //Offset is the ammount that each existing layer will need to be moved down by
        int offset = layerHeight;

        //Create the new layer
        CALayer *newLayer = [CALayer layer];
        [newLayer setBounds:CGRectMake(0, 0, self.view.layer.bounds.size.width, layerHeight)];
        [newLayer setAnchorPoint:CGPointMake(0, 0)];
        [newLayer setPosition:CGPointMake(0, 0-offset)];
        [newLayer setBackgroundColor:[[UIColor redColor] CGColor]];

        //Add the new layer to the view's layer and to layerArray
        [self.view.layer addSublayer:newLayer];
        [layerArray insertObject:newLayer atIndex:0];

        //loop through all layers and move them to their new position...
        for(int i=0;i<[layerArray count]; i++) {
            CALayer *currentLayer = [layerArray objectAtIndex:i];

            CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
            [anim setValue:@"stackLayer" forKey:@"kind"];
            [anim setValue:[NSNumber numberWithInt:i] forKey:@"index"];
            [anim setDelegate:self];
            [anim setDuration:1.0];

            currentLayer.actions = [NSDictionary dictionaryWithObject:anim forKey:@"position"];
            currentLayer.position = CGPointMake(0, currentLayer.position.y + offset);
        }
    }
}

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    //Make sure the last layer finished animating...
    if([[anim valueForKey:@"kind"] isEqual:@"stackLayer"] && [[anim valueForKey:@"index"] isEqual:[NSNumber numberWithInt:[layerArray count]-1]]) {
        animationLocked = NO;
    }
}

2 个答案:

答案 0 :(得分:3)

你非常接近。我只想将循环中的代码更改为:

for(int i=0;i<[layerArray count]; i++)
{
  CALayer *currentLayer = [layerArray objectAtIndex:i];

  CGPoint endPoint = CGPointMake(0, currentLayer.position.y + offset);
  CGPoint currentPoint = [currentLayer position];

  CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
  [anim setFromValue:[NSValue valueWithCGPoint:currentPoint]];
  [anim setToValue:[NSValue valueWithCGPoint:endPoint]];
  [anim setDelegate:self];
  [anim setDuration:1.0];

  [anim setValue:@"stackLayer" forKey:@"kind"];
  [anim setValue:[NSNumber numberWithInt:i] forKey:@"index"];

  [currentLayer setPosition:endPoint];
  [currentLayer addAnimation:anim forKey:@"position"];
}

这将确保您的图层从当前位置动画到偏移位置,并设置图层的位置,以便在动画完成时它不会恢复到其起始位置 - 尽管您可能无法获得如果你在同一个运行循环中完成它,它可以正常工作。您可能希望设置图层并在视图加载时添加它们,然后将它们设置为对其他某个操作的响应动画,或者通过调用 -performSelector:withObject:afterDelay 传递一些延迟来允许它们它有机会排队等待以后的运行循环迭代。

答案 1 :(得分:-1)

您必须在动画中设置新的图层位置,而不是直接在图层上设置。

CAlayer *layer = ...

CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation"];]
positionAnimation.fromValue = oldPOsition
positionAnimation.toValue = newPosition
positionAnimation.duration = n;
positionAnimation.delegate = self;          

[layerToAnimate addAnimation:layerAnimation forKey:@"transform.translation"]