User transition between two UIViews

I have two kinds of "A" and "B". A float in the middle of the window (this is not a full screen). B, the view that will replace A, is full-screen. I would like to write a custom transition that flips A to show B on the back, but at the same time scales the rectangle with flipping so that when the flip ends, B is full-screen.

I tried using the flip transitions available with the FromView: toView: duration: options: complete transition, but I can make it just click across the screen and not start the flip from frame A and end with a B frame.

I know that I can do 3D-like transformations for presentation layers, but I'm not sure which set of animation APIs I should use to achieve this. One thing I tried was to change the properties of the view layer in the transition animation blockWithView: duration: options: animations: completion: but this did not work, as it seems to only confirm modifications to the properties of the view.

Can someone point me in the right direction? I would be very grateful.

UPDATE: Here is my code so far for this effect. You can see a video of what he is doing here: http://www.youtube.com/watch?v=-xNMD2fGRwg

 CGRect frame = [[UIApplication easybookDelegate] rootViewController].view.bounds ; float statusHeight = [UIApplication sharedApplication].statusBarFrame.size.height ; frame.origin.y = statusHeight ; frame.size.height -= statusHeight ; self.view.frame = frame ; // self.view is view "B" // Put the snapshot as thet topmost view of our view UIImageView *imageView = [[UIImageView alloc] initWithImage:image] ; // image is a snapshot of view "A" imageView.frame = self.view.bounds ; [self.view addSubview:imageView] ; [self.view bringSubviewToFront:imageView] ; // Pre-transform our view (s=target/current, d=target-current) CGAffineTransform transform = CGAffineTransformIdentity ; // Translate our view CGPoint center = CGPointMake(screenOrigin.x + (image.size.width/2.0), screenOrigin.y + (image.size.height/2.0)) ; float dX = center.x - self.view.center.x ; float dY = center.y - self.view.center.y ; NSLog( @"dx: %f, dy: %f" , dX, dY ) ; transform = CGAffineTransformTranslate(transform, dX, dY) ; // Scale our view float scaleWFactor = image.size.width / self.view.frame.size.width ; float scaleHFactor = image.size.height / self.view.frame.size.height ; transform = CGAffineTransformScale(transform,scaleWFactor, scaleHFactor) ; self.view.transform = transform ; [[[UIApplication easybookDelegate] rootViewController].view addSubview:self.view] ; // Perform the animation later since implicit animations don't seem to work due to // view "B" just being added above and hasn't had a chance to become visible. Right now // this is just on a timer for debugging purposes. It'll probably be moved elsewhere, probably // to view "B" -didMoveToSuperview double delayInSeconds = 0.3; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ [UIView transitionWithView:self.view duration:3 options:UIViewAnimationOptionTransitionFlipFromRight| UIViewAnimationOptionCurveEaseOut animations:^(void) { [imageView removeFromSuperview] ; self.view.transform = CGAffineTransformIdentity ; } completion:^(BOOL finished){ [self.view removeFromSuperview] ; [navController presentModalViewController:self animated:NO] ; }] ; }); [imageView release]; 

code>

+6
iphone core-animation uiview
source share
6 answers

I have done this before. Here is the gist of how I did it:

  • View A is on screen
  • Create a View B, give it a frame that makes it fullscreen, but don't add it to the screen yet
  • View B has a UIImageView as its top view
  • Grab UIImage View A and set it as View B image

     UIGraphicsBeginImageContext(view.bounds.size); [viewA.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); viewB.imageView.image = image; 
  • Set the view B-transformation (scale and translation) so that it is reduced to the size of View A and is located where View A is on the screen

  • Add view B to screen
  • At this point, the user did not notice anything, because View B looks exactly like View A
  • Now run the animation block in which you
    • Set [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView:ViewB
    • set View B transform to CGAffineTransformIdentity
    • remove View B imageview from View B

The result is an animation that looks like this: View A flips and zooms to fill the screen with View B as the opposite side.

+3
source share

Checkout this svn repository:

 http://boondoggle.atomicwang.org/lemurflip/ 

This displays two views.

+1
source share

This is a simple example that I made for you :-) Start with this ... Try to understand this ... Read the Documentation, and then you can do what you want -)

 - (void)moveTable:(UITableView *)table toPoint:(CGPoint)point excursion:(CGFloat)excursion { [UIView beginAnimations:nil context:nil]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDuration:0.5]; [table setCenter:point]; // scaling CABasicAnimation *scalingAnimation = (CABasicAnimation *)[table.layer animationForKey:@"scaling"]; if (!scalingAnimation) { scalingAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; scalingAnimation.duration=0.5/2.0f; scalingAnimation.autoreverses=YES; scalingAnimation.removedOnCompletion = YES; scalingAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; scalingAnimation.fromValue=[NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0, 0.0, 0.0)]; scalingAnimation.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeTranslation(excursion, 0.0, 0.0)]; } [table.layer addAnimation:scalingAnimation forKey:@"scaling"]; [UIView commitAnimations]; 

}

+1
source share

Try something like this. As long as the frame is not full-screen to begin with, then the animation should just click A. When you add a subview to the view in a flipped translation, it is added to the back of that view, so viewing the frame is the one you want to change.

 [UIView beginAnimations:@"flipopen" context:nil]; [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self cache:TRUE]; [a addSubview:b]; a.frame = b.frame; [UIView commitAnimations]; 
0
source share

I assume that you just want to change the image of the image while you flip and scale it. The following code flips the image using the default animation, scales it to a different view frame, and sets the image:

 [UIView beginAnimations:nil context:nil]; [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.imageViewA cache:NO]; [UIView setAnimationDuration:2]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(animationFinished:)]; self.imageViewA.frame = self.imageViewB.frame; self.imageViewA.image = self.imageViewB.image; [UIView commitAnimations]; 

if you want to display representation A again as your small floating view with a different image, you can simply set it as a frame and image without an animation block in the AnimationDidStopSelector method, which you can set

 -(void)animationFinished:(id)context { self.imageViewA.frame = tinyRect; self.imageViewA.image = [UIImage imageNamed:@"a.jpg"]; } 

where tinyRect is the floating source frame of the view.

0
source share

A bit rough around the edges, but here's what I did using block animation. The next click opens, centers it and enters full-screen mode:

 // the view on the other side of the card UIView* redView = [[UIView alloc]initWithFrame:CGRectMake(0.0, 0.0, viewToFlip.frame.size.width, viewToFlip.frame.size.height)]; redView.backgroundColor = [UIColor redColor]; // add a green square to the red view so we have something else to look at UIView* greenSquare = [[UIView alloc]initWithFrame:CGRectMake(10.0, 10.0, 20.0, 20.0)]; greenSquare.backgroundColor = [UIColor greenColor]; [redView addSubview:greenSquare]; // the flip animation [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationCurveLinear animations:^{ // rotate 90 degrees [viewToFlip.layer setTransform: CATransform3DRotate(viewToFlip.layer.transform, -M_PI/2, 0.0, 1.0, 0.0)]; } completion:^(BOOL finished){ // now that we're 90 degrees, swap one view for the other // but if we add it now, the view will be backwards, so flip the original view back [viewToFlip.layer setTransform: CATransform3DRotate(viewToFlip.layer.transform, M_PI, 0.0, 1.0, 0.0)]; [viewToFlip addSubview:redView]; // now let continue our rotation [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationCurveLinear animations:^{ // rotate the last 90 degrees [viewToFlip.layer setTransform: CATransform3DRotate(viewToFlip.layer.transform, -M_PI/2, 0.0, 1.0, 0.0)]; } completion:^(BOOL finished){ [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationCurveLinear animations:^{ // animate the views to the center of the screen and adjust their bounds to fill up the screen [viewToFlip setCenter:CGPointMake(self.view.center.x, self.view.center.y)]; [viewToFlip setBounds:CGRectMake(0.0, 0.0, self.view.frame.size.width, self.view.frame.size.height)]; [redView setCenter:CGPointMake(self.view.center.x, self.view.center.y)]; [redView setBounds:CGRectMake(0.0, 0.0, self.view.frame.size.width, self.view.frame.size.height)]; } completion:nil]; }]; }]; 
0
source share

All Articles