View's position is changed while adding a child view? - ios

I have two views side by side(left & right).At one time i am just showing one view other view not visible because i have moved that view out of scene towards the right of screen.I have set the x position in such a way so that it is not visible(view is always to the right of screen so not visible).So i press next button which is near to first view then my second view is visible & first view is hidden. I have used animation to slide thew view from left to right & right to left.
-(void)handleSingleTapGesture:(UITapGestureRecognizer *)tapGestureRecognizer
{
NSLog(#"first");
CGFloat screenWidth = 0.0;
if(IS_IPHONE_6)
{
screenWidth=self.view.frame.size.width-120.0;
}
if(IS_IPHONE_5)
{
screenWidth=self.view.frame.size.width-68.0;
}
NSLog(#"New screen width is %f",screenWidth);
[self.back_view setHidden:false];
[self.front_view setHidden:true];
[UIView animateWithDuration:0.5 animations:^{
self.front_view.frame = CGRectOffset(self.front_view.frame, -screenWidth, 0.0);
self.back_view.frame = CGRectOffset(self.back_view.frame, -screenWidth, 0.0);
}];
}
-(void)handleSingleTapGesture_one:(UITapGestureRecognizer *)tapGestureRecognizer
{
CGFloat screenWidth = 0.0;
if(IS_IPHONE_6)
{
screenWidth=self.view.frame.size.width-120.0;
}
if(IS_IPHONE_5)
{
screenWidth=self.view.frame.size.width-68.0;
}
NSLog(#"New screen width is %f",screenWidth);
[self.back_view setHidden:true];
[self.front_view setHidden:false];
[UIView animateWithDuration:0.5 animations:^{
self.front_view.frame = CGRectOffset(self.front_view.frame, screenWidth, 0.0);
self.back_view.frame = CGRectOffset(self.back_view.frame, screenWidth, 0.0);
}];
}
On the backView i have added a subview on bottom-right so when ever i try to add the view inside that view then then main view is shifted to the right i don't know why.Please tell me how can i get the solution?

Related

Resizing a UIView hides subviews

I have a view controller with a view that doesn't fill the screen and has transparency around the edges. In said view I have a tableview, some buttons and a text field.
I have all of the controls attached to the bottom of the view with constraints and the tableview attached to the top.
Everything resizes fine when the device is put in landscape/portrait mode, but when I manually resize it when the keyboard appears, the bottom of the view just moves up and covers the lowest elements.
Resizing/animation code:
- (void)keyboardDidShow:(NSNotification *)notification {
//Stuff to get keyboard frames
void (^animations)() = ^() {
CGRect mainViewFrame = self.mainView.frame;
CGRect tableViewFrame = self.tableView.frame;
tableViewFrame.size.height = tableViewFrame.size.height - 50;
mainViewFrame.size.height = mainViewFrame.size.height - 50;
CGFloat paddingOffset = self.view.frame.size.height - self.mainView.frame.origin.y - self.mainView.frame.size.height;
mainViewFrame.origin.y = (mainViewFrame.origin.y - keyboardEndFrame.size.height + paddingOffset - 8);
self.mainView.frame = mainViewFrame;
[self.tableView setNeedsLayout];
[self.mainView setNeedsLayout];
};
[UIView animateWithDuration:animationDuration
delay:0.0
options:(animationCurve << 16)
animations:animations
completion:^(BOOL finished){
if (finished) {
NSLog(#"Finished animating");
self.acceptBottomConstraint.constant = 5;
self.cancelBottomConstraint.constant = 5;
}
}];
}
This is my UI in the Storyboard:
This is what it looks like after resizing:

iOS UIView animation when table view scroll?

I want animation like home screen of this app.This screen has a view (with a label on it) on top and a table view under it. When i scroll the table the top view and title on it become small with animation and after a specific point it becomes like navigation bar with title in centre. And the same thing when i scroll down.
Here is what i tried so far
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGPoint offset = scrollView.contentOffset;
NSLog(#"y is::: %f", offset.y);
if (offset.y > 0 && offset.y < 16 && self.topView.frame.size.height > 64) {
[UIView animateWithDuration:0.8 animations:^{
CGRect rect = self.topView.frame;
rect.size.height = rect.size.height-offset.y;
self.topView.frame = rect;
}completion:^(BOOL finish){
}];
}
else if(offset.y <= 0 && offset.y > -16 && self.topView.frame.size.height < 80)
{
[UIView animateWithDuration:0.8 animations:^{
CGRect rect = self.topView.frame;
rect.size.height = 80;
self.topView.frame = rect;
}completion:^(BOOL finish){
}];
}
}
Note that my top view initial height is 80 and i want to make it 64 when scroll up and vice versa.
with this code the view height animated but it depends upon animation duration.So if i scroll fast then it is not working properly.The original app i mentioned have very smooth animation. How could i achieve that?
Screen shot of original App-
These screen shots showing three different scroll position, please note the "MySurgery" text on top.1- Larger text and right align.
2- small text and near centre position
3- smaller text and centralised(like navigation bar)
I think you dont need animation for this, you just need some calculations and setting frame of the top view. like,
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGPoint offset = scrollView.contentOffset;
if (offset.y>0 && offset.y<64) {
[topView layoutIfNeeded];
CGRect viewFrame = topView.frame;
viewFrame.size.height--;
topView.frame = viewFrame;
}
}
Note that layoutIfNeeded is required if your view is using autolayout

Show scaled UIViewController in another UIViewController

I want to display a scaled down "preview" of another ViewController in another ViewController. Is this possible? No interaction are needed so it can basically be a screenshot, but scaled down. I can be solved by manually take a screenshot and save it as an image, but the ViewController contains a lot of localizations and are constantly updated, so if this can be done programatically.
https://www.dropbox.com/s/kd5vinrym1k7afk/Screenshot%202014-05-13%2015.20.17.png
Is this possible?
Edit: the sub view is stored in a storyboard
Edit: This is how I've solved it:
//Load the viewcontroller and view
previewViewController = [self.storyboard instantiateViewControllerWithIdentifier:[PLACEHOLDER_VIEWCONTROLLER_NAMES objectAtIndex:self.identifier]];
[self addChildViewController:previewViewController];
[self.placeholderView.superview addSubview:previewViewController.view];
previewViewController.view.transform = CGAffineTransformMakeScale(scale*2, scale*2);
CGPoint center = self.placeholderView.center;
center.y += 25;
previewViewController.view.center = center;
Use the viewController.view and then scale it down like:
viewController.view.transform = CGAffineTransformMakeScale(0.5, 0.5);
Add your another view controller view as subview to first viewcontroller
[UIView animateWithDuration:2.0f animations:^{
InnerView.userInteractionEnabled = NO;
//Always starts from original scale
InnerView.transform = CGAffineTransformMakeScale(0.5, 0.5);
//Incremental scale
//InnerView.transform = CGAffineTransformScale(InnerView.transform, 0.5, 0.5);
} completion:^(BOOL finished) {
NSLog(#"in Half size");
}];
[UIView animateWithDuration:2.0f animations:^{
InnerView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
InnerView.userInteractionEnabled = YES;
NSLog(#"Normal size");
}];

Creating a larger flip-side view for 'tile' in storyboard

I currently have a Container View Controller which is home to a button. When this is pressed, I want the view to flip and grow, similar to iTunes on the iPad.
Main View Controller Layout:
Flipping the Container:
When the flip button is pressed, I intend to use this code (Inside the container view's View Controller) to flip the container:
FrontVC *cb = [[FrontVC alloc]initWithFrame:CGRectMake(0, 0, 92, 65)];
FlipVC *cf = [[FlipVC alloc]initWithFrame:CGRectMake(0, 0, 92, 65)];
[UIView transitionWithView:self.view
duration:1
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
// Remove last view
for (UIView *subview in self.view.subviews) {
[subview removeFromSuperview];
}
[self.view addSubview:(displayingPrimary ? cb: cf)];
}
completion:^(BOOL finished) {
if (finished) {
displayingPrimary = !displayingPrimary;
}
}];
This works well if the two views are the same size, and I can lay out the views using code. FrontVC and FlipVC are sub-classes of UIView.
I was thinking about doing something like this to move the view to the centre of the screen, but I'm stuck from there. Hey, I don't even know if this would work! Is there a better way to do this?
if (!displayingPrimary) {
self.view.center = CGPointMake(320.0f, 480.0f);
cb.center = CGPointMake(320.0f, 480.0f);
}
else
{
self.view.center = CGPointMake(59, 324);
}
What I Am Aiming For:
Ideally, I would like to be able to design the flip view in storyboard, and have the 'tile' grow, similar to iTunes:
Whereas in my example I would like it to look like this:
How would I be able to design this in storyboard? If I try to make a view controller, I am unable to resize it to the size that I would like the flip size view controller to be.
The FlipView project is quite polished and looks exactly as the iTunes flip does. I used two imageViews for the demo project. The actual flip code is as follows:
- (IBAction)flip
{
UIView *fromView, *toView;
CGPoint pt;
CGSize size;
CGFloat sense;
if(showingView == a) {
fromView = a;
toView = b;
pt = BORIGIN;
size = BRECT.size;
sense = -1;
} else {
fromView = b;
toView = a;
pt = AORIGIN;
size = ARECT.size;
sense = 1;
}
[UIView animateWithDuration:TIME/2 animations:^
{
CATransform3D t = CATransform3DIdentity;
t.m34 = M34;
t = CATransform3DRotate(t, M_PI_2*sense, 0, 1, 0);
containerView.layer.transform = t;
containerView.frame = CRECT; // midpoint
NSLog(#"Container MID Frame %#", NSStringFromCGRect(containerView.frame));
}
completion:^(BOOL isFinished)
{
toView.layer.transform = CATransform3DMakeRotation(M_PI*sense, 0, 1, 0);
[UIView animateWithDuration:TIME/2 animations:^
{
[fromView removeFromSuperview];
[containerView addSubview:toView];
CATransform3D t = CATransform3DIdentity;
t.m34 = M34;
t = CATransform3DRotate(t, M_PI*sense, 0, 1, 0);
containerView.layer.transform = t; //finish the flip
containerView.frame = (CGRect){ pt, size};
} completion:^(BOOL isFinished)
{
NSLog(#"Container Frame %#", NSStringFromCGRect(containerView.frame));
NSLog(#"A Frame %#", NSStringFromCGRect(b.frame));
NSLog(#"B Frame %#", NSStringFromCGRect(b.frame));
toView.layer.transform = CATransform3DIdentity;
containerView.layer.transform = CATransform3DIdentity;
showingView = showingView == a ? b : a;
}];
}];
}
http://dl.dropbox.com/u/60414145/FlipView.zip
EDIT: One way to work around the resizing a real view with real controls in it might have is to take a snapshot of that view, use the snapshot while zooming/flipping, and in the final completion block switch out the image for the real view. That is:
create a UIImage of your current small view when the user taps the image
create a UIImage of the final view, rendered into a context as its natural size
use the two images in the container view, for the animation
in the final completion block, remove your imageView from view and put the second view now in self.view subviews
I did a rough code (not at all perfect) on this (hope it is what you are looking for). Have a look into it. I created a baseView and two flip views, after the first flip, I increased the frame size of baseView and added the second flip view on it.I am not an expert of Story Board, so I havent used it here.
FlipTest
-anoop

How do I make an expand/contract transition between views on iOS?

I'm trying to make a transition animation in iOS where a view or view controller appears to expand to fill the whole screen, then contract back to its former position when done. I'm not sure what this type of transition is officially called, but you can see an example in the YouTube app for iPad. When you tap one of the search result thumbnails on the grid, it expands from the thumbnail, then contracts back into the thumbnail when you return to the search.
I'm interested in two aspects of this:
How would you make this effect when transitioning between one view and another? In other words, if view A takes up some area of the screen, how would you transition it to view B which takes up the whole screen, and vice versa?
How would you transition to a modal view this way? In other words, if UIViewController C is currently showing and contains view D which takes up part of the screen, how do you make it look like view D is turning into UIViewController E which is presented modally on top of C?
Edit: I'm adding a bounty to see if that gets this question more love.
Edit: I've got some source code that does this, and Anomie's idea works like a charm, with a few refinements. I had first tried animating the modal controller's view (E), but it didn't produce the effect of feeling like you're zooming into the screen, because it wasn't expanding all the stuff around the thumbnail view in (C). So then I tried animating the original controller's view (C), but the redrawing of it made for a jerky animation, and things like background textures did not zoom properly. So what I wound up doing is taking an image of the the original view controller (C) and zooming that inside the modal view (E). This method is substantially more complex than my original one, but it does look nice! I think it's how iOS must do its internal transitions as well. Anyway, here's the code, which I've written as a category on UIViewController.
UIViewController+Transitions.h:
#import <Foundation/Foundation.h>
#interface UIViewController (Transitions)
// make a transition that looks like a modal view
// is expanding from a subview
- (void)expandView:(UIView *)sourceView
toModalViewController:(UIViewController *)modalViewController;
// make a transition that looks like the current modal view
// is shrinking into a subview
- (void)dismissModalViewControllerToView:(UIView *)view;
#end
UIViewController+Transitions.m:
#import "UIViewController+Transitions.h"
#implementation UIViewController (Transitions)
// capture a screen-sized image of the receiver
- (UIImageView *)imageViewFromScreen {
// make a bitmap copy of the screen
UIGraphicsBeginImageContextWithOptions(
[UIScreen mainScreen].bounds.size, YES,
[UIScreen mainScreen].scale);
// get the root layer
CALayer *layer = self.view.layer;
while(layer.superlayer) {
layer = layer.superlayer;
}
// render it into the bitmap
[layer renderInContext:UIGraphicsGetCurrentContext()];
// get the image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// close the context
UIGraphicsEndImageContext();
// make a view for the image
UIImageView *imageView =
[[[UIImageView alloc] initWithImage:image]
autorelease];
return(imageView);
}
// make a transform that causes the given subview to fill the screen
// (when applied to an image of the screen)
- (CATransform3D)transformToFillScreenWithSubview:(UIView *)sourceView {
// get the root view
UIView *rootView = sourceView;
while (rootView.superview) rootView = rootView.superview;
// convert the source view's center and size into the coordinate
// system of the root view
CGRect sourceRect = [sourceView convertRect:sourceView.bounds toView:rootView];
CGPoint sourceCenter = CGPointMake(
CGRectGetMidX(sourceRect), CGRectGetMidY(sourceRect));
CGSize sourceSize = sourceRect.size;
// get the size and position we're expanding it to
CGRect screenBounds = [UIScreen mainScreen].bounds;
CGPoint targetCenter = CGPointMake(
CGRectGetMidX(screenBounds),
CGRectGetMidY(screenBounds));
CGSize targetSize = screenBounds.size;
// scale so that the view fills the screen
CATransform3D t = CATransform3DIdentity;
CGFloat sourceAspect = sourceSize.width / sourceSize.height;
CGFloat targetAspect = targetSize.width / targetSize.height;
CGFloat scale = 1.0;
if (sourceAspect > targetAspect)
scale = targetSize.width / sourceSize.width;
else
scale = targetSize.height / sourceSize.height;
t = CATransform3DScale(t, scale, scale, 1.0);
// compensate for the status bar in the screen image
CGFloat statusBarAdjustment =
(([UIApplication sharedApplication].statusBarFrame.size.height / 2.0)
/ scale);
// transform to center the view
t = CATransform3DTranslate(t,
(targetCenter.x - sourceCenter.x),
(targetCenter.y - sourceCenter.y) + statusBarAdjustment,
0.0);
return(t);
}
- (void)expandView:(UIView *)sourceView
toModalViewController:(UIViewController *)modalViewController {
// get an image of the screen
UIImageView *imageView = [self imageViewFromScreen];
// insert it into the modal view's hierarchy
[self presentModalViewController:modalViewController animated:NO];
UIView *rootView = modalViewController.view;
while (rootView.superview) rootView = rootView.superview;
[rootView addSubview:imageView];
// make a transform that makes the source view fill the screen
CATransform3D t = [self transformToFillScreenWithSubview:sourceView];
// animate the transform
[UIView animateWithDuration:0.4
animations:^(void) {
imageView.layer.transform = t;
} completion:^(BOOL finished) {
[imageView removeFromSuperview];
}];
}
- (void)dismissModalViewControllerToView:(UIView *)view {
// take a snapshot of the current screen
UIImageView *imageView = [self imageViewFromScreen];
// insert it into the root view
UIView *rootView = self.view;
while (rootView.superview) rootView = rootView.superview;
[rootView addSubview:imageView];
// make the subview initially fill the screen
imageView.layer.transform = [self transformToFillScreenWithSubview:view];
// remove the modal view
[self dismissModalViewControllerAnimated:NO];
// animate the screen shrinking back to normal
[UIView animateWithDuration:0.4
animations:^(void) {
imageView.layer.transform = CATransform3DIdentity;
}
completion:^(BOOL finished) {
[imageView removeFromSuperview];
}];
}
#end
You might use it something like this in a UIViewController subclass:
#import "UIViewController+Transitions.h"
...
- (void)userDidTapThumbnail {
DetailViewController *detail =
[[DetailViewController alloc]
initWithNibName:nil bundle:nil];
[self expandView:thumbnailView toModalViewController:detail];
[detail release];
}
- (void)dismissModalViewControllerAnimated:(BOOL)animated {
if (([self.modalViewController isKindOfClass:[DetailViewController class]]) &&
(animated)) {
[self dismissModalViewControllerToView:thumbnailView];
}
else {
[super dismissModalViewControllerAnimated:animated];
}
}
Edit: Well, it turns out that doesn't really handle interface orientations other than portrait. So I had to switch to animating the transition in a UIWindow using a view controller to pass along the rotation. See the much more complicated version below:
UIViewController+Transitions.m:
#interface ContainerViewController : UIViewController { }
#end
#implementation ContainerViewController
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation {
return(YES);
}
#end
...
// get the screen size, compensating for orientation
- (CGSize)screenSize {
// get the size of the screen (swapping dimensions for other orientations)
CGSize size = [UIScreen mainScreen].bounds.size;
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) {
CGFloat width = size.width;
size.width = size.height;
size.height = width;
}
return(size);
}
// capture a screen-sized image of the receiver
- (UIImageView *)imageViewFromScreen {
// get the root layer
CALayer *layer = self.view.layer;
while(layer.superlayer) {
layer = layer.superlayer;
}
// get the size of the bitmap
CGSize size = [self screenSize];
// make a bitmap to copy the screen into
UIGraphicsBeginImageContextWithOptions(
size, YES,
[UIScreen mainScreen].scale);
CGContextRef context = UIGraphicsGetCurrentContext();
// compensate for orientation
if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
CGContextTranslateCTM(context, size.width, 0);
CGContextRotateCTM(context, M_PI_2);
}
else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
CGContextTranslateCTM(context, 0, size.height);
CGContextRotateCTM(context, - M_PI_2);
}
else if (self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
CGContextTranslateCTM(context, size.width, size.height);
CGContextRotateCTM(context, M_PI);
}
// render the layer into the bitmap
[layer renderInContext:context];
// get the image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// close the context
UIGraphicsEndImageContext();
// make a view for the image
UIImageView *imageView =
[[[UIImageView alloc] initWithImage:image]
autorelease];
// done
return(imageView);
}
// make a transform that causes the given subview to fill the screen
// (when applied to an image of the screen)
- (CATransform3D)transformToFillScreenWithSubview:(UIView *)sourceView
includeStatusBar:(BOOL)includeStatusBar {
// get the root view
UIView *rootView = sourceView;
while (rootView.superview) rootView = rootView.superview;
// by default, zoom from the view's bounds
CGRect sourceRect = sourceView.bounds;
// convert the source view's center and size into the coordinate
// system of the root view
sourceRect = [sourceView convertRect:sourceRect toView:rootView];
CGPoint sourceCenter = CGPointMake(
CGRectGetMidX(sourceRect), CGRectGetMidY(sourceRect));
CGSize sourceSize = sourceRect.size;
// get the size and position we're expanding it to
CGSize targetSize = [self screenSize];
CGPoint targetCenter = CGPointMake(
targetSize.width / 2.0,
targetSize.height / 2.0);
// scale so that the view fills the screen
CATransform3D t = CATransform3DIdentity;
CGFloat sourceAspect = sourceSize.width / sourceSize.height;
CGFloat targetAspect = targetSize.width / targetSize.height;
CGFloat scale = 1.0;
if (sourceAspect > targetAspect)
scale = targetSize.width / sourceSize.width;
else
scale = targetSize.height / sourceSize.height;
t = CATransform3DScale(t, scale, scale, 1.0);
// compensate for the status bar in the screen image
CGFloat statusBarAdjustment = includeStatusBar ?
(([UIApplication sharedApplication].statusBarFrame.size.height / 2.0)
/ scale) : 0.0;
// transform to center the view
t = CATransform3DTranslate(t,
(targetCenter.x - sourceCenter.x),
(targetCenter.y - sourceCenter.y) + statusBarAdjustment,
0.0);
return(t);
}
- (void)expandView:(UIView *)sourceView
toModalViewController:(UIViewController *)modalViewController {
// get an image of the screen
UIImageView *imageView = [self imageViewFromScreen];
// show the modal view
[self presentModalViewController:modalViewController animated:NO];
// make a window to display the transition on top of everything else
UIWindow *window =
[[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
window.hidden = NO;
window.backgroundColor = [UIColor blackColor];
// make a view controller to display the image in
ContainerViewController *vc = [[ContainerViewController alloc] init];
vc.wantsFullScreenLayout = YES;
// show the window
[window setRootViewController:vc];
[window makeKeyAndVisible];
// add the image to the window
[vc.view addSubview:imageView];
// make a transform that makes the source view fill the screen
CATransform3D t = [self
transformToFillScreenWithSubview:sourceView
includeStatusBar:(! modalViewController.wantsFullScreenLayout)];
// animate the transform
[UIView animateWithDuration:0.4
animations:^(void) {
imageView.layer.transform = t;
} completion:^(BOOL finished) {
// we're going to crossfade, so change the background to clear
window.backgroundColor = [UIColor clearColor];
// do a little crossfade
[UIView animateWithDuration:0.25
animations:^(void) {
imageView.alpha = 0.0;
}
completion:^(BOOL finished) {
window.hidden = YES;
[window release];
[vc release];
}];
}];
}
- (void)dismissModalViewControllerToView:(UIView *)view {
// temporarily remove the modal dialog so we can get an accurate screenshot
// with orientation applied
UIViewController *modalViewController = [self.modalViewController retain];
[self dismissModalViewControllerAnimated:NO];
// capture the screen
UIImageView *imageView = [self imageViewFromScreen];
// put the modal view controller back
[self presentModalViewController:modalViewController animated:NO];
[modalViewController release];
// make a window to display the transition on top of everything else
UIWindow *window =
[[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
window.hidden = NO;
window.backgroundColor = [UIColor clearColor];
// make a view controller to display the image in
ContainerViewController *vc = [[ContainerViewController alloc] init];
vc.wantsFullScreenLayout = YES;
// show the window
[window setRootViewController:vc];
[window makeKeyAndVisible];
// add the image to the window
[vc.view addSubview:imageView];
// make the subview initially fill the screen
imageView.layer.transform = [self
transformToFillScreenWithSubview:view
includeStatusBar:(! self.modalViewController.wantsFullScreenLayout)];
// animate a little crossfade
imageView.alpha = 0.0;
[UIView animateWithDuration:0.15
animations:^(void) {
imageView.alpha = 1.0;
}
completion:^(BOOL finished) {
// remove the modal view
[self dismissModalViewControllerAnimated:NO];
// set the background so the real screen won't show through
window.backgroundColor = [UIColor blackColor];
// animate the screen shrinking back to normal
[UIView animateWithDuration:0.4
animations:^(void) {
imageView.layer.transform = CATransform3DIdentity;
}
completion:^(BOOL finished) {
// hide the transition stuff
window.hidden = YES;
[window release];
[vc release];
}];
}];
}
Whew! But now it looks just about like Apple's version without using any restricted APIs. Also, it works even if the orientation changes while the modal view is in front.
Making the effect is simple. You take the full-sized view, initialize its transform and center to position it on top of the thumbnail, add it to the appropriate superview, and then in an animation block reset the transform and center to position it in the final position. To dismiss the view, just do the opposite: in an animation block set transform and center to position it on top of the thumbnail, and then remove it completely in the completion block.
Note that trying to zoom from a point (i.e. a rectangle with 0 width and 0 height) will screw things up. If you're wanting to do that, zoom from a rectangle with width/height something like 0.00001 instead.
One way would be to do the same as in #1, and then call presentModalViewController:animated: with animated NO to present the actual view controller when the animation is complete (which, if done right, would result in no visible difference due to the presentModalViewController:animated: call). And dismissModalViewControllerAnimated: with NO followed by the same as in #1 to dismiss.
Or you could manipulate the modal view controller's view directly as in #1, and accept that parentViewController, interfaceOrientation, and some other stuff just won't work right in the modal view controller since Apple doesn't support us creating our own container view controllers.
After watching the Youtube iPad animation, I figured out that it's just an illusion. Let's say that there's a SearchViewController for the search results, and a DetailViewController for the video itself, and the additional info of the video.
DetailViewController has a method like - (id)initWithFullscreen which starts the view controller using the full screen space with the video.
So the sequence goes like this:
SearchViewController presents its results.
User clicks on a video.
DetailViewController is created with initWithFullscreen, but not presented
The "Zoom in" animation begins. (Notice that we are still on the SearchViewController, and this animation is just a simple View animation)
The "Zoom in" animation ends, presents the DetailViewController with animated:NO (as Anomie mentioned).
The DetailViewController is now presented, and using full space.
It doesn't seem that the youtube app is doing anything fancier, the give-away was that the "Zoom in" animation zooms to a black square, before presenting the full video.

Resources