Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate UIView to fold one half onto the other half

I have the following problem. I want to write a method with which i can fold one half of a UIView onto the other half.

The algorithm is clear to me (at least i think so, but maybe i forgot something).

  1. Create a rendered image of the UIView
  2. split it depending on which half i want to fold onto the other
  3. add the corresponding halfs of the rendered image to the corresponding layers
  4. add the two layers to a backgroundlayer with white background and no contents (it is just there to make a white background to cover up the original layer of the view)
  5. add the backgroundlayer to the views layer
  6. set the transform for the folding layer
  7. start the animation

Should work, but doesn't! And I have no idea why. :(

Here is the sourcecode of the Method:

-(void)foldView:(UIView *) view withDuration: (NSTimeInterval) duration toSide: (NSString*) side withReverse: (bool) reverse andRepeatCount:(float) repeatCount
{
    //create Screenshot from view to fold
    UIGraphicsBeginImageContext(view.bounds.size);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *img_view = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    //Bildausschnitte festlegen
    CGRect rect_closingImageHalf = view.bounds;    
    CGRect rect_fixedImageHalf = view.bounds;    

    CGPoint pt_anchorOpeningImageHalf;
    CGPoint pt_anchorFixedImageHalf;

    CATransform3D transform;

    CALayer *lay_closingImageHalf;
    CALayer *lay_fixedImageHalf;
    lay_fixedImageHalf.masksToBounds = YES;
    lay_closingImageHalf.masksToBounds = YES;
    //get white backside of layer which folds
    lay_closingImageHalf.doubleSided = NO;


    //white backgroundlayer to hide the layer of the image
    CALayer *backgroundAnimationLayer = [CALayer layer];
    backgroundAnimationLayer.frame = view.frame;
    backgroundAnimationLayer.backgroundColor = [[UIColor whiteColor] CGColor];

    //determine direction in which to fold    
    if ([side isEqualToString:k_side_vonLinks]) 
    {
        rect_closingImageHalf = CGRectMake(0, 0, img_view.size.width / 2, img_view.size.height);
        rect_fixedImageHalf = CGRectMake(img_view.size.width / 2, 0, img_view.size.width / 2, img_view.size.height);

        pt_anchorOpeningImageHalf = CGPointMake(1.0, 0.5);        
        pt_anchorFixedImageHalf = CGPointMake(0.5, 0.5);

        transform = CATransform3DMakeRotation(M_PI, 0, 1.0, 0);
    }
    else if([side isEqualToString:k_side_vonRechts])
    {
        rect_closingImageHalf = CGRectMake(img_view.size.width / 2, 0, img_view.size.width / 2, img_view.size.height);
        rect_fixedImageHalf = CGRectMake(0, 0, img_view.size.width / 2, img_view.size.height);

        pt_anchorOpeningImageHalf = CGPointMake(0.0, 0.5);
        pt_anchorFixedImageHalf = CGPointMake(0.5, 0.5);   

        transform = CATransform3DMakeRotation(M_PI, 0, 1.0, 0);
    }
    else if([side isEqualToString:k_side_vonOben])
    {
        rect_closingImageHalf = CGRectMake(0, 0, img_view.size.width, img_view.size.height / 2);
        rect_fixedImageHalf = CGRectMake(0, img_view.size.height / 2, img_view.size.width, img_view.size.height / 2);

        pt_anchorOpeningImageHalf = CGPointMake(0.5, 1.0);
        pt_anchorFixedImageHalf = CGPointMake(0.5, 0.5);

        transform = CATransform3DMakeRotation(M_PI, 1.0, 0, 0);
    }
    else if([side isEqualToString:k_side_vonUnten])
    {
        rect_closingImageHalf = CGRectMake(0, img_view.size.height / 2, img_view.size.width, img_view.size.height / 2);
        rect_fixedImageHalf = CGRectMake(0, 0, img_view.size.width, img_view.size.height / 2);

        pt_anchorOpeningImageHalf = CGPointMake(0.5, 0.0);
        pt_anchorFixedImageHalf = CGPointMake(0.5, 0.5);

        transform = CATransform3DMakeRotation(M_PI, 1.0, 0, 0);
    }

    CGImageRef img_closingHalf = CGImageCreateWithImageInRect( [img_view CGImage], rect_closingImageHalf);
    CGImageRef img_fixedHalf = CGImageCreateWithImageInRect( [img_view CGImage], rect_fixedImageHalf);    

    lay_closingImageHalf.anchorPoint = pt_anchorOpeningImageHalf;
    lay_fixedImageHalf.anchorPoint = pt_anchorFixedImageHalf;


    //add the rendered image of the view to the backgroundLayer
    [backgroundAnimationLayer addSublayer:lay_fixedImageHalf];
    [backgroundAnimationLayer addSublayer:lay_closingImageHalf];
    lay_closingImageHalf.contents = (__bridge id)img_closingHalf;
    lay_fixedImageHalf.contents = (__bridge id)img_fixedHalf;


    [view.layer addSublayer:backgroundAnimationLayer];

    //add perspective
    transform.m34 = 1.0f / 2500.0f;

    //animate the folding of the layer
    CABasicAnimation *flipAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    flipAnimation.toValue = [NSValue valueWithCATransform3D:transform];
    flipAnimation.duration = duration;
    flipAnimation.autoreverses = reverse;
    flipAnimation.repeatCount = repeatCount;
    flipAnimation.delegate = self;
    flipAnimation.removedOnCompletion = NO;
    flipAnimation.fillMode = kCAFillModeForwards;

    [backgroundAnimationLayer addAnimation:flipAnimation forKey:@"fold"];
}

If someone of you has an idea why it doesn't work i would be very glad if he can help. I googled almost a day and read many samples but i cannot find the mistake. I also looked into AFKPageFLipper which is a really great example for this task, but unfortunately it didn't help me to find out whats wrong with my code.

Hope that someone can help me.

like image 923
Maverick1st Avatar asked Jan 25 '26 07:01

Maverick1st


1 Answers

Have a look at these two projects that include the effect you are trying to create:

https://github.com/blommegard/SBTickerView

https://github.com/raweng/FlipView

like image 104
Martin Gjaldbaek Avatar answered Jan 27 '26 21:01

Martin Gjaldbaek