BlackMouse
BlackMouse

Reputation: 4552

Core animation: Flipp a view

I'm trying to transition from one view to another. I know there's the "[UIView transitionWithView..." but I'm going to add more complex things to the animation layer and need to write the code myself.

The code below works, but has three problems:

  1. When the backside view appears, it's flipped horizontal.

  2. After the animation has completed, I add the backside view and remove the frontside. During the animation, both view becomes a little bigger due to the perspective (m34), so when the completionBlock adds the new view to the screen, there's an ugly snap back to it's original size.

  3. I need to delay the CATransaction with a block (runBlockAfterDelay). If I don't have the block, the animation will not run.

Thanks in advance

For extra credit :), Is it possible to have the code in a class method? e.g + (void)flippFromView...

    - (void)flipFromView:(UIView *)fromView toView:(UIView *)toView spaceBetweenLayers:     (CGFloat)spaceBetweenLayers duration:(CGFloat)duration delay:(CGFloat)delay (void))block
    {
    // Move flipp view back, behind front view
    toView.layer.transform = CATransform3DMakeTranslation(0.0, 0.0, -spaceBetweenLayers);;

    // Layer that will handle the animation
    CALayer *rootLayer = [CALayer layer];
    rootLayer.frame = self.frame;
    rootLayer.position = fromView.layer.position;
    [self.layer addSublayer:rootLayer];

    //Transform Layer
    CATransformLayer *transformLayer = [CATransformLayer layer];
    [transformLayer addSublayer:fromView.layer];
    [transformLayer addSublayer:toView.layer];
    [rootLayer addSublayer:transformLayer];


    [self runBlockAfterDelay:delay block:^{

        [CATransaction begin];
        [CATransaction setValue:@(duration) forKey:kCATransactionAnimationDuration];

        // Completion block
        [CATransaction setCompletionBlock:^{

            // App crashes with EXC_BAD_ACCESS if we don't move the layer back to the super layer before removing the rootLayer
            [self.layer addSublayer:fromView.layer];
            [self.layer addSublayer:toView.layer];

            // Add new, and remove old layer
            [self addSubview:toView];
            [fromView removeFromSuperview];

            // Set Z position
            fromView.layer.zPosition = -10;
            toView.layer.zPosition = 10;

            // Clean up
            [rootLayer removeFromSuperlayer];
        }];

        // Flipp
        CATransform3D flippTransform = CATransform3DMakeRotation(DegreesToRadians(180), 0, 1, 0);
        flippTransform.m34 = 1.0f/500.0f;
        rootLayer.sublayerTransform = flippTransform;

        [CATransaction commit];
    }];
}

Upvotes: 0

Views: 135

Answers (1)

Fogmeister
Fogmeister

Reputation: 77631

It is flipped horizontally because that's what you've just done. You've just flipped the view 180degrees.

The way to get around this is to do the animation in stages.

  1. Animate the view to flip it 90 degrees (to the right for this example) so that it's flat on to the screen and invisible.
  2. Swap out the "front" view with the "back" view.
  3. Now change the transform on the view so that is flipped 90 degrees to the left. Don't animate this, just change it.
  4. Now animate the view to flip it back to normal.

It will look like the view has rotated 180 degrees but in fact it has not changed at all at the end of the animation. It just looks like it changed.

Upvotes: 3

Related Questions