CoverFlow: The Easy Way


SnapShot1203559906.png

After chatting with iPhone developer Cobra about his most recent UICoverFlowLayer example, I decided to simplify UICoverFlowLayer creation. What I found was this: programming cover flow is eerily reminiscent of programming tables. Like tables, you create a data source method in your main application. This data source supplies your coverflow layer with images on demand. And, like tables, you build delegate methods that react to selection changes. When a user taps on an image, you can catch that selection change and do something about it.


The hard part is getting your head around it being a layer. UICoverFlowLayers are layers and not views. Views are first class display objects. Layers are not. To make this work, you slide your layer into some kind of containing view. You customize that view so it can forward user events and the run loop's heartbeat back to the layer. This lets it react to those events. In the following sections, you'll see how to create a really simple UICoverFlowLayer example.

Creating a View container

As the UICoverFlowLayer class is just a layer, not a stand-alone view, I created a CoverFlowView class. Its entire reason for being is to encompass the layer and channel events to it. As you can see, there's not much to it. It's a basic UIView with one instance variable, which points to the cover flow layer. Any mouse events get sent to that layer, and the ticking heartbeat of the main event loop is passed along as well.

@interface CoverFlowView : UIView {
   id cfLayer;
}
@end

@implementation CoverFlowView

// React To User Events
- (void) reactTo:(id)event flow:(int)flow
{
CGRect rect = GSEventGetLocationInWindow(event);
[cfLayer dragFlow: flow atPoint: rect.origin];
}
- (void) mouseUp: (id)event {[self reactTo:event flow:2];}
- (void) mouseDown: (id)event {[self reactTo:event flow:0];}
- (void) mouseDragged: (id)event {[self reactTo:event flow:1];}
- (BOOL) ignoresMouseEvents {return NO;}

// Initialize so it knows about its cfLayer
- (void) setLayer: (id)aLayer {cfLayer = aLayer;}

// Forward the heartbeat
- (void) tick {[cfLayer displayTick];}
@end


Creating the Cover Flow Layer


To build cover flow, you build the cover flow view, allocate the cover flow layer and insert it into place in the view. Notice how you specify the number of covers to be used when you first create the layer.


    // Create the main UIView
CGRect mainRect = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
mainView = [[CoverFlowView alloc] initWithFrame:mainRect];

// Add the cover flow Layer
cfLayer = [[UICoverFlowLayer alloc] initWithFrame:mainRect
numberOfCovers: [picList count]];
[cfLayer setDelegate:self];

[[mainView _layer] addSublayer:cfLayer];
[mainView setLayer: cfLayer];


Cover Flow layers require a placeholder layer. This layer is the placeholder for all your art. It is a core surface that exactly matches the dimensions of each coverflow image to be used. All images use the same placeholder dimensions.


    // Add the placeholder layer
[cfLayer setPlaceholderImage: [self createCoreSurface]];

Another, optional, layer is the information layer. I found it simple enough to create a UITextLabel, grab its layer and attach that as the cover flow's info layer:


    label = [[UITextLabel alloc] init]; 
[cfLayer setInfoLayer:[label _layer]];

Make sure when creating your view, that you use a relatively bright foreground color and a clear (alpha set to 0.0f) background color so the info layer "floats" over the cover flow images.


    [label setBackgroundColor:getColor(0.0f, 0.0f, 0.0f, 0.0f)];
[label setColor:getColor(1.0f, 1.0f, 1.0f, 0.75f)];

Supplying Images

In this example, I perform a simple search for thumbnails in an iPhone's DCIM/100APPLE folder. This has the advantage of producing very small images that load quickly and do not bog down a complex cover flow. If you need to work with larger data, you may want to pre-scale in advance to keep your memory load down and keep your cover flow moving smoothly. Using the icon.pngs from the /Applications folder also works well.

Supply the UIImages (or more specifically imageRefs from UIImages) by their numerical index. The requests do not come in any specific order. Use the natural order of your data to match the index to the picture.

// Image Data Source Method
- (void) coverFlow:(id)cf requestImageAtIndex: (int)idx quality: (int)q
{
   id whichImg = [PICDIR stringByAppendingPathComponent:
                    [picList objectAtIndex:idx]];
   id img = [UIImage imageAtPath:whichImg];
   [cfLayer setImage:[img imageRef]  atIndex:idx type:q];
}

Moving between Images

Cover flow layers produce simple selection did change delegate method calls when the selected item changes. You can use that change to do something. In this example, I update the information text with the name of the selected thumbnail.

// Selection Delegate Method -- User picked an object
- (void) coverFlow: (id) cf selectionDidChange: (int) idx
{
   [label setText:[picList objectAtIndex:idx]];
}

Sample Code

I've posted the complete sample code here for your reference.

AddThis Social Bookmark Button
Comments (24)

24 Comments

Vu Manh Hung said:

Good job! I need sample but the sample may be deleted. Could you send the CoverFlow sample for me at manhhungk6@gmail.com?
Thank you.

Ashley said:

Could u send me this sample too, please...
ibulatova@gmail.com

hrgpac said:

PicBrowser uses CoverFlow for searching images in the Web in both orientations, check it out in:

http://www.youtube.com/v/WBl6byJU3R4
http://www.youtube.com/v/3R-fuu_yE5E
http://www.youtube.com/watch?v=xOZ1Pw6l3sY
http://www.youtube.com/watch?v=tBJCVUie2Dc

In 1.1 the animation's performance (to be approved by apple :S and posted some time ago) is enhanced.

jacob said:

Could u plz send me the sample code of this to rockon_005@yahoo.com my id ...i m working on this and i need this..
Thanks in advance..

This looks cool! Could you send the CoverFlow sample for me at jonboy100uk@gmail.com as the link you provided doesn't seem to work. Thanks

Jason said:

Hi dude, great work, cant find your code to download. could you please send it also to me ?
jason_lee@hotmail.de
thanxs

Trev said:

Hey guys, it's a shame they haven't kept this up to date. I found the code by buying the book but this code no longer works on 2.2 onwards which is really annoying (cover flow is not officially supported in the iPhone SDK - this example worked only on 2.1), if you find a better example I'd really like to know!

Yusdenis said:

Could u plz send me the sample code of CoverFloew to yusdenis81@gmail.com
I am working on this and i need this..

Thanks

jlr said:

Could u plz send me the sample code of CoverFloew to jlruggeri@free.fr
I am working on this and i need this..

Avinash said:

Its cool.. but you are using undocumented api's which apple does not approve. I used same in my app but apple rejected my app.... Is there any other implementation which does not use apples undocumented api's. Please let me know...

Eric said:

Hello,

Could you send me please the sample code to eric@epitech.net

Thank you,

Ketan said:

Hi,

In this animation if i want to rotate all images. mean to say that When Selected Cover is one then in left side back image is the last one

Jonas said:

Hi!
Can anyone please send me the complete sample code?

koska88@hotmail.com

Thank you!

Keep up the good work!

Amr Ibrahim said:

Can you send it to me too
amr_i_m@yahoo.com
I bought the book already btw :) a great one
Regards,
Amr

Marlon said:

Could you send the CoverFlow sample for me at marlonvolz@gmail.com? Thank you.

dhanunjaya said:

Can you please send me the sample code for creating cover flow plzzzzzz help me.........

Sandor said:

Hi guys can anyone send me the example code to my email: sandor.szeman@freemail.hu

Thanks in advice!

Sandor

mic said:

Can you pls send a complete source code, my email is microzone98@hotmail.com.

Thanks.

Ilias said:

Hi! Just a question... Is it possible to zoom-in when you click in an image and zoom-out when you click again? (I have images in my app instead of the colors that you have.)

Peter Nguyen said:

Could you please send me the complete source code for your cover flow example? I would love to learn how you did this.

Thank you.

Pete

gatloc said:

Could you please send me the complete source code for your cover flow example? gaetano@web2mobiledesign.com I would love to learn how you did this.
Thank you.

gatloc

arslan said:

Hi, nice effort. I couldn't find the sample code. Could you please send me the sample code. arslan_jutt@hotmail.com. Thanks in advance.

Regards,
Arslan Ilyas

Dijesh said:

Can anyone please send me the sample source code for creating cover flow please to dijeshmathew@gmail.com. Thanks in advance.
dij

Erfan said:

Can anyone please send me the sample project or code for this at erfan.eps@gmail.com. Thanks in advance. :)