Page Flip: Difference between revisions

From iPhone Development Wiki
Line 45: Line 45:
          
          
         [uiv_container.layer addAnimation:ag_group forKey:@"Flip View"];
         [uiv_container.layer addAnimation:ag_group forKey:@"Flip View"];
  }
==Flipping Closed==
Now, we have the page up, so next we need to rotate it down back to flat. Rotate it another 90 degrees in the Y direction, this time we need to rotate on the right side of it (so all the text looks right when its rotating down. This gives the illusion that there is a front and a back to the view.
  -(void)pageFlip {
  NSLog(@"page opening");
 
  uiv_container.layer.anchorPoint = CGPointMake(1.0f,0.5f);
 
  CABasicAnimation *ba_animation = [CABasicAnimation animationWithKeyPath:@"transform"];
 
  ba_animation.removedOnCompletion = NO;
  ba_animation.duration = 2.0;
  ba_animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
 
  //This time we need to start from the position where the frame is 90 degrees rotated
  CATransform3D t_start = CATransform3DMakeRotation(M_PI/2, 0.0, -1.0, 0.0);
 
    //Need the opposite of the previous value so that the edge is sized correctly from the beginning
    t_start.m14 = 0.001f;
 
  ba_animation.fromValue = [NSValue valueWithCATransform3D:t_start];
 
  //Now rotate it down to the identity matrix
    ba_animation.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
 
  CAAnimationGroup *ag_group = [CAAnimationGroup animation];
  ag_group.delegate = self;
  ag_group.duration = 2.0;
 
  [ag_group setValue:[NSNumber numberWithInt:2] forKey:@"Animation Tag"];
  ag_group.animations = [NSArray arrayWithObjects:ba_animation, nil];
 
    [uiv_container.layer addAnimation:ag_group forKey:@"Flip View"];
  }
==Animation Did Finish selector==
Finally, we need something to manage everything when the animation ends. So here we tell it to run the the page flip after the page open finishes
  - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
  NSLog(@"animation did stop");
      // Get the tag from the animation, we use it to find the
      // animated UIView
      NSNumber *tag = [theAnimation valueForKey:@"Animation Tag"];
  if([tag intValue] == 1) {
  uiv_front.hidden = YES;
  [uiv_front removeFromSuperview];
  [self.view addSubview:uiv_back];
  uiv_back.hidden = NO;
  [self pageOpen];
  } if([tag intValue] == 2) {
 
  }
   }
   }

Revision as of 23:00, 17 November 2010

Introduction

Ok, so maybe you need a page flip animation. There are lots of UIView default animations, that look really good, but my UI designed really busted me and was like "NO, I WANT A BARN DOOR FLIP". Anyway, there isn't a default way that I could find to do this. So I had to take a dive into core animation land and dig deep.

Flipping Open

Aight, so to flip a view open, we take the view, and rotate it using core animation by 90 degrees in y direction around the left side of it. All makes sense right? So, get a UIView as a container and add anything you want to flip onto it.

  -(void)pageOpen {
       //Make sure the container is visible and remove any other previous animations from it
       [uiv_container.layer removeAllAnimations];
       [uiv_front setHidden:NO];
       [uiv_container setUserInteractionEnabled:NO];
      
       //Sets the anchor point to the middle of the left side
       uiv_container.layer.anchorPoint = CGPointMake(0.0f,0.5f);
      
       //Set up a new animation to describe the transform
       CABasicAnimation *ba_animation = [CABasicAnimation animationWithKeyPath:@"transform"];
      
       ba_animation.removedOnCompletion = NO;
       
       //This is the time it takes for the animation to complete, here its 2 seconds
       ba_animation.duration = 2.0;
        
       //Using different timing functions will change the animation speed at different points. Ex: kCAMediaTimingFunctionEaseIn
       ba_animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
       
       //Start from the identity matrix. If you haven't every done 3D programming, the Identity matrix is basically the normal matrix of anything
       ba_animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
       
       //Set up the end matrix. Here we are setting it to 90 degrees in the Y direction
       CATransform3D t_end = CATransform3DMakeRotation(M_PI/2, 0.0, -1.0, 0.0);
       
       //This value controls the size of the end, modifying it like this makes it get bigger, making it more like a 3D rotation
       t_end.m14 = -0.001f;
       
       ba_animation.toValue = [NSValue valueWithCATransform3D:t_end];
      
       //Add the animation to an animation group, this lets us track the animation as it finishes
       CAAnimationGroup *ag_group = [CAAnimationGroup animation];
       ag_group.delegate = self;
       ag_group.duration = 2.0;
       
       [ag_group setValue:[NSNumber numberWithInt:1] forKey:@"Animation Tag"];
       ag_group.animations = [NSArray arrayWithObjects:ba_animation, nil];
       
       [uiv_container.layer addAnimation:ag_group forKey:@"Flip View"];
  }

Flipping Closed

Now, we have the page up, so next we need to rotate it down back to flat. Rotate it another 90 degrees in the Y direction, this time we need to rotate on the right side of it (so all the text looks right when its rotating down. This gives the illusion that there is a front and a back to the view.

  -(void)pageFlip {
  	NSLog(@"page opening");
  	 
  	uiv_container.layer.anchorPoint = CGPointMake(1.0f,0.5f);
  	
  	CABasicAnimation *ba_animation = [CABasicAnimation animationWithKeyPath:@"transform"];
  
  	ba_animation.removedOnCompletion = NO;
  	ba_animation.duration = 2.0;
  	ba_animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
  	
  	//This time we need to start from the position where the frame is 90 degrees rotated
  	CATransform3D t_start = CATransform3DMakeRotation(M_PI/2, 0.0, -1.0, 0.0);
  
   	//Need the opposite of the previous value so that the edge is sized correctly from the beginning
   	t_start.m14 = 0.001f;
  	
  	ba_animation.fromValue = [NSValue valueWithCATransform3D:t_start];
  
  	//Now rotate it down to the identity matrix
   	ba_animation.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
  
  	CAAnimationGroup *ag_group = [CAAnimationGroup animation];
  	ag_group.delegate = self;
  	ag_group.duration = 2.0;
  
  	[ag_group setValue:[NSNumber numberWithInt:2] forKey:@"Animation Tag"];
  	ag_group.animations = [NSArray arrayWithObjects:ba_animation, nil];
  
   	[uiv_container.layer addAnimation:ag_group forKey:@"Flip View"];
  }

Animation Did Finish selector

Finally, we need something to manage everything when the animation ends. So here we tell it to run the the page flip after the page open finishes

  - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
  	NSLog(@"animation did stop");
      // Get the tag from the animation, we use it to find the
      // animated UIView
      NSNumber *tag = [theAnimation valueForKey:@"Animation Tag"];
  	if([tag intValue] == 1) {
  		uiv_front.hidden = YES;
  		[uiv_front removeFromSuperview];
  		[self.view addSubview:uiv_back];
  		uiv_back.hidden = NO;
  		[self pageOpen];
  	} if([tag intValue] == 2) {
  		
  	}
  }