Page Flip: Difference between revisions

From iPhone Development Wiki
(+ proper syntax highlighting)
 
(3 intermediate revisions by one other user not shown)
Line 5: Line 5:
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.
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.


<source lang=objc>
  -(void)pageOpen {
         //Make sure the container is visible and remove any other previous animations from it
         //Make sure the container is visible and remove any other previous animations from it
         [uiv_container.layer removeAllAnimations];
         [uiv_container.layer removeAllAnimations];
Line 44: Line 46:
          
          
         [uiv_container.layer addAnimation:ag_group forKey:@"Flip View"];
         [uiv_container.layer addAnimation:ag_group forKey:@"Flip View"];
  }
</source>
==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.
<source lang=objc>
  -(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"];
  }
</source>
==Animation Did Stop==
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
<source lang=objc>
  - (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) {
 
  }
  }
</source>
==Conclusion==
Hopefully this gets you on the correct path for a flip animation. Good luck. Need, any help? Let me know!

Latest revision as of 06:16, 21 January 2014

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 Stop

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) {
   		
   	}
   }

Conclusion

Hopefully this gets you on the correct path for a flip animation. Good luck. Need, any help? Let me know!