views:

530

answers:

3

Hi! This is my first question her so please be gentle: I have followig animation code running smoothly on the simulator as well as on the real device (I am testng on iPhone 3GS 3.1.2). Animation is a simple transition between the 2 views, something like book page flipping.

One diffrence betwen simulator an real device (The problem I cannot investigate - solve) is that on real device when animation finishes - after rotation has been done animated view blink (show for a split of second) for a moment before it goes hidden. On the simulator this 'unexpected' blink does not happen.

Here is the animation code:

-(void)flip{
    UIView *animatedView;

    // create an animation to hold the page turning
    CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    transformAnimation.removedOnCompletion = NO;
    transformAnimation.delegate = self;
    transformAnimation.duration = ANIMATION_TIME;
    transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    // this is the basic rotation by 90 degree along the y-axis
    CATransform3D endTransform = CATransform3DMakeRotation(3.141f/2.0f,
                    0.0f,
                    -1.0f,
                    0.0f);
    // these values control the 3D projection outlook
    endTransform.m34 = 0.001f;
    endTransform.m14 = -0.0015f;


    // start the animation from the current state
    transformAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    transformAnimation.toValue = [NSValue valueWithCATransform3D:endTransform];
    animatedView = screenShot;

    // Create an animation group to hold the rotation and possibly more complex animation in the future
    CAAnimationGroup *theGroup = [CAAnimationGroup animation];

    // Set self as the delegate to receive notification when the animation finishes
    theGroup.delegate = self;
    theGroup.duration = ANIMATION_TIME;
    // CAAnimation-objects support arbitrary Key-Value pairs, we add the UIView tag
    // to identify the animation later when it finishes
    [theGroup setValue:[NSNumber numberWithInt:animatedView.tag] forKey:@"animated"];
    // Here you could add other animations to the array
    theGroup.animations = [NSArray arrayWithObjects:transformAnimation,nil];
    theGroup.removedOnCompletion = NO;
    // Add the animation group to the layer
    if (animatedView.layer.anchorPoint.x != 0.0f) 
    {
     animatedView.layer.anchorPoint = CGPointMake(0.0f, 0.5f);
     float yy = animatedView.center.x - (animatedView.bounds.size.width / 2.0f);
     animatedView.center = CGPointMake(yy, animatedView.center.y);
    }

    if(![animatedView isDescendantOfView:self.view])[self.view addSubview:animatedView];
    screenShot.hidden = NO;
    animatedView.hidden = NO;


    [animatedView.layer addAnimation:theGroup forKey:@"flip"];

}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {

    screenShot.hidden = YES;

}
A: 

Not sure I understand completely what you are seeing but it's possible you're seeing something caused by the speed difference between the device and the simulator. The simulator is considerably faster than the device so something that "blinks" very quickly might do so too fast for the human eye to catch on the simulator.

TechZen
A: 

Oof. That's annoying. I think it is that there's a split-second between when animation stops and when that line of code executes. If only there were an animationWillStop: method! You might try, instead of screenShot.hidden = YES, screenShot.alpha = 0. I doubt it will make any difference speed-wise, but it might be worth a shot? You could also fade out the view as part of the animation, but I don't think you want to do that.

The only other thing I can think of is to setup an NSTimer with an interval just under your animation time. Something like:

[NSTimer scheduledTimerWithTimeInterval:(ANIMATION_TIME - .001) target:self selector:@selector(hideTheView) userInfo:nil repeats:NO];

And then implement that hideTheView method, of course.

Ian Henry
Thank you! - trick with screenShot.alpha = 0 does not work.However - trick with NSTmer works. BUT - this solution does not seem to be elegant and I do not believe every animation which changes position of the UIview should implement this.I am glad it works anyway - at least I know direction in which shall I look for an answer. Thank you - I do not have enought reputation points to vote for this answer, simple thank you must be enought at the momemt ;-)
Lukasz
+3  A: 

Try setting theGroup's and / or transformAnimation's fillMode to kCAFillModeForwards:

theGroup.fillMode = kCAFillModeForwards;

This should cause your animation to persist once its active duration has completed. I've used this to remove an end-of-animation flicker before.

Brad Larson
Great - this works perfecttly!Respect Brad.
Lukasz
Worth mentioning:It seems it works only when used together with:theGroup.removedOnCompletion = NO;
Lukasz