iPhone Development

Just another iPhone Blog

iOS Open Folder Animation

As I was fiddling with my iPad,  Open Folder Animation in iOS caught my attention. After giving it a serious though on how to achieve it, It looked Trivial.

iOS Folder View

 

Let us get together to write a piece of code which does this cool animation.

 

1. Plan

iOS_Folder_View_Plan.png

We can achieve this using 3 Main Layers

1. Layer -1 (Main View) : The Lowest layer contains the main screen which stores the main content

2. Layer -2  (Folder View): The Folder View, which hosts the Folder Icons. Once the Folder Opens, This is the only view which is active accepting the Touch Event. This layer resides above Layer-1

3. Layer-2.1 (Arrow ) : The Arrow, which points to the selected folder. This is movable on x-Axis.

4. Layer-3 (Layer to host Bottom part of Main Content View) : This layer hosts the bottom part of the Main Content View (Layer -1) i.e from point where Folder View ( Layer-2) occupies to the end of the Main Content View. This Layer is place above the Folder View (Layer-2 ) in terms of Level. In Terms of position on screen, this layer is placed just below the Folder View(Layer-2)

 

2. Execution

We can achieve Open Folder Animation effect in 3 Simple Steps

STEP 1: Capture the Main View Content into an image

  • Capturing Main View Content Image can be achieve using renderInContext: API. as shown in code snippet below
  • Clip the Main View into two parts, One part is the visible portion above the Folder view and rest of the image would be hosted in Layer -3. The Trick used in sample code below to avoid the cutting of the image into two parts, is by setting the Layer-3 bounds, such that it should hide the top portion (Part-1) of the Main Content view.

-(void)captureImageFromPointAndSetupMaskView:(CGPoint)selectedFolderPoint

{

UIGraphicsBeginImageContext(mMainBackgroundView.frame.size);

//capture the main content view

[mMainBackgroundView.layer renderInContext:UIGraphicsGetCurrentContext()];

UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext();

[mBottomPartOfMainBackgroundView setImage:backgroundImage];

//set the bounds such that the we hide the part of the main content image, which is visible just above the Folder View.

//This gets the continuation effect on the image once the folder view appears on screen

[mBottomPartOfMainBackgroundView.superview setBounds:CGRectMake(0.0, selectedFolderPoint.y + mSelectedArrowTipView.frame.size.height, mMainBackgroundView.frame.size.width, mMainBackgroundView.frame.size.height)];


}

 

STEP 2: Layout the Folder View(Layer 2 & 2.1) and Bottom Part Of Main Content View (Layer -3)

  • Folder View and Arrow View are grouped in Single View.
  • Place The Arrow View such that it is right below and to the Center of the Tapped Folder Icon Tapped
  • Place the Folder View Just below Arrow View

-(void)layoutBottomPartOfMainViewRelativeToPointInMainView:(CGPoint)selectedFolderPoint

{

//Place the Folder View Just below Arrow View

CGRect folderViewFrame = [mFolderView frame];

folderViewFrame.origin.y = floorf(selectedFolderPoint.y);

[mFolderView setFrame:folderViewFrame];

//making sure the View which displays bottom part of Main Backgorund View is just below  the Folder View

CGRect maskFrame = mBottomPartOfMainBackgroundView.superview.frame;

maskFrame.origin.y = folderViewFrame.origin.y + mSelectedArrowTipView.frame.size.height;

mBottomPartOfMainBackgroundView.superview.frame = maskFrame;

//Place The Arrow View such that it is right below and to the Center of the Tapped Folder Icon Tapped

[UIView setAnimationsEnabled:NO];

mSelectedArrowTipView.center = CGPointMake(selectedFolderPoint.x, 0.0);

CGRect arrowFrame = mSelectedArrowTipView.frame;

arrowFrame.origin.y = 0.0;

mSelectedArrowTipView.frame = arrowFrame;

 

[UIView setAnimationsEnabled:YES];

}


 

STEP 3- Push The Layer-3 which hosts the other part of the Main Content View

-(void)layoutFinalFrameOfBottomPartOfMainContentView

{

//Push The Layer-3 which hosts the other part of the Main Content View

CGRect maskFrame = mBottomPartOfMainBackgroundView.superview.frame;

maskFrame.origin.y = mFolderView.frame.origin.y + mFolderView.frame.size.height;

mBottomPartOfMainBackgroundView.superview.frame = maskFrame;

}

 

Thats it !! The above 3 steps would be called upon tapping a Folder  Icon as show in below code snippet

-(IBAction)openFolder:(id)sender

{

//get the center point of the tapped folder

CGPoint selectedFolderPoint = CGPointMake([sender center].x, [sender frame].origin.y + [sender frame].size.height);

if( mFolderView.hidden )//if folder is not opened

{

//open folder animation

//STEP 1: Capture the Main View Content into an image

[self captureImageFromPointAndSetupMaskView:selectedFolderPoint];

//STEP 2: Layout the Folder View(Layer 2 & 2.1) and Bottom Part Of Main Content View (Layer -3)

[self layoutBottomPartOfMainViewRelativeToPointInMainView:selectedFolderPoint];

[UIView beginAnimations:@"FolderOpen" context:NULL];

[UIView setAnimationDuration:0.5];

[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

//captures the main background view’s image

mFolderView.hidden=NO;

mBottomPartOfMainBackgroundView.superview.hidden=NO;

//STEP 3- Push The Layer-3 which hosts the other part of the Main Content View

[self layoutFinalFrameOfBottomPartOfMainContentView];

[UIView commitAnimations];

}

else {

//close folder animation

[UIView beginAnimations:@"FolderClose" context:NULL];

[UIView setAnimationDuration:0.5];

[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

[UIView setAnimationDidStopSelector:@selector(animation:didFinish:context:)];

[UIView setAnimationDelegate:self];

//restore the layout and hide the folder view after animation

[self closeFolder:selectedFolderPoint];

[UIView commitAnimations];

}

}

 

3. Result

Download the Full Source Code Here : iOS Open Folder Animation.zip

A Video of the Sample Code can be found here: iOS Open Folder Animation Video

If you like this post, Please leave your feedback / comment and Share this (See below for sharing options) to spread to all others who might be interested :-)

Happy Coding :-)

About these ads

13 responses to “iOS Open Folder Animation

  1. Pingback: Tweets that mention iOS Open Folder Animation « iPhone Development -- Topsy.com

  2. farmski March 19, 2011 at 1:58 pm

    I guess you are farmiliure with the folder enhancer tweek?

    I am wanting this animation style incorporated in the tweek.. so that it opens up into a full screen folder.. with the ability to have the freedom that you have with tbe enhancer tweek!!

    I contacted the developer of folder enhancer.. but he said animations slow things down on older devices so no plans to implement it..

    I’m on iPhone 4 4.2.1

    could you do me a code to embalm this.. in the easiest way to apply the tweek too.. I dont know much about this stuff. unless you tell me where to put the file via ssh or ifile

    cheers

    farmz

  3. bakus April 11, 2011 at 6:07 am

    how would you implement that in a uitableViewCell so when the user does a longPress, the cell height changes (tableView heightForRowAtIndexPath) and displays the folderView. thx

    • bharath2020 April 11, 2011 at 4:44 pm

      I would still go with the same approach as discussed in this post

      1. Detect Long press by subclassing UITableViewCell or other efficient means
      2. Once Long Press is detected, capture the current screen
      3. In the FolderView, display the captured screen. Also, i would capture the UITableViewCell only so that I place it at center of FolderView and animate as if we are increasing the cell height

      [Please note that the Folder view's background is an Image of the captured screen. and hence one would think as if we are dividing the screen into half. that is the trick here.]

      Hope this helps.

      • bakus April 11, 2011 at 8:34 pm

        Thanks, this was really helpful, but using this technique it is impossible to scroll the tableView in case a cell half on the screen is pressed (there is no way of scrolling up to view the folderView).

      • bharath2020 April 12, 2011 at 3:10 am

        What I understand from your statement is, you have to scroll the tableview while the Folderview is kept open, In that case, you are right, this technique does not work. we may have to look for improving this.

        Can you please help me understand your expected outcome with a screenshot?. I am keen to look at this.

      • bakus April 12, 2011 at 11:18 pm

        the way I’m trying this is to implement a folderView (UIViewController) that I would add to the Longpressed cell contentView. First I’m calling UILongPressGestureRecognizer while creating each cell so it detects when a cell is longPressed. Second I call ( pressedIndexPath = [self.tableView indexPathForRowAtPoint:[longPressedRecognizer locationInView:self.tableView]]; ) to find the index of the pressed cell and call
        if (p_pressedIndexPath != nil)
        [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:p_pressedIndexPath] withRowAnimation:UITableViewRowAnimationNone]; to reload the selected cell. Third I change the height of that cell by calling:
        ((UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
        if (pressedIndexPath != nil && [pressedIndexPath compare:indexPath] == NSOrderedSame)
        return newHeight; “new height is the previous size of the cell + the size of the view that I’m going to add to it. Lastly, in the (UITableView *)tableView cellForRowAtIndexPath, I also do a check before returning the cell to see if a cell is pressed “if (pressedIndexPath != nil && [pressedIndexPath compare:indexPath] == NSOrderedSame)” then add the View to the content.
        It’s a lot of code and might be confusing, but … dont really know how to give you the pic so let me know a way that would be easier for u to get.
        Thanks for the help

      • bharath2020 April 14, 2011 at 3:35 am

        Got your approach, but cant clearly imagine how the final output should look like. If you have got the final snapshot of how the screen should look like when folderview is visible, then it would help me

      • Bakus April 14, 2011 at 2:53 pm

        Check this video and pay attention to the effect when a twit is touched http://www.engadget.com/2011/04/14/tweetbot-might-replace-your-ios-twitter-client-video/

    • bakus April 14, 2011 at 7:38 pm

      here is a video that demonstrate what I wanna achieve. http://www.youtube.com/watch?v=ZBOHGzE6TNY

      • bharath2020 May 13, 2011 at 6:50 pm

        I am replying this way too late, by which time you might have got the solution. If not, try this link http://developer.apple.com/library/ios/#samplecode/TableViewUpdates/Listings/ReadMe_txt.html

        Try Pinch gesture on the tableview in the sample.

  4. Seth Gholson (@sethgho) August 26, 2011 at 7:35 pm

    I’ve been trying to implement this approach in an app, but no matter how many times I rework it I keep running into the same problem. It’s as if the mask view for the bottom image’s superview isn’t working.

    When I press the button, it does everything right, except mask the view. An image of the whole screen shifts down the appropriate amount, but from the very top.

    Any ideas? Any help would be appreciated.

    • bharath2020 August 27, 2011 at 7:53 am

      I guess your have missed to clip the image’s superview into two halts.. Please check step 1 – clipping main view into two parts as described in post. If I am wrong in understanding your problem, you can PM me ur sample code.. I will be glad to help you..

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 29 other followers

%d bloggers like this: