Cocoa Programming for Mac OS X - Aaron Hillegass [124]
The central class in Core Animation is CALayer, which you can think of as a building block. Its appearance can be configured in numerous ways through its properties. Among them are position, size, image contents, background color, border, shadow, and corner radius. It’s also possible to mask a layer with another, as well apply a 3D transform. Most properties can be animated simply by setting a new value.
Layers are similar to views in some ways. Like views, layers are arranged in a hierarchy. A view can be covered with a layer, and that layer can have sublayers. You can also draw into a CALayer, not unlike a custom view. Unlike views, however, layers do not receive user input events (mouse, keyboard) and are not part of the responder chain.
Manipulating a layer’s properties will animate it, but we sometimes need more control. CAAnimation and its subclasses let us fine-tune animations. CATransaction can be used to group and synchronize multiple animations, as well as to disable animations temporarily.
Scattered
Let’s create an application that uses Core Animation to drive the interface. This particular application will load all the images it finds in a folder and display them using CALayer objects (Figure 33.1). For this exercise, we’ll use dot notation for setting properties on Core Animation objects.
Figure 33.1. Completed Application
In Xcode, create a new project called Scattered with a Class Prefix of Scattered. Set it to not be document based. Since we will be using Core Animation, add the QuartzCore framework. Switch to the project navigator and select the Scattered project item. In the project editor, select the Scattered target and click the button below Linked Frameworks and Libraries. Select QuartzCore.framework.
Next, open ScatteredAppDelegate.h. Import QuartzCore.h and add the following instance variables:
#import #import @interface ScatteredAppDelegate : NSObject IBOutlet NSView *view; CATextLayer *textLayer; } @property (assign) IBOutlet NSWindow *window; @end Open MainMenu.xib. Select the window in the Interface Builder dock to show the window, then drag a Custom View onto it. Size it to fill the window. Make sure that it is reasonably large, at least 500 × 500. Right-click on the Scattered App Delegate in the dock to show its Connections panel. Drag a connection from the view outlet to the custom view you created (Figure 33.2). Figure 33.2. Custom View in Window Open ScatteredAppDelegate.m and make the following additions: #import "ScatteredAppDelegate.h" @interface ScatteredAppDelegate () - (void)addImagesFromFolderURL:(NSURL *)url; - (NSImage *)thumbImageFromImage:(NSImage *)image; - (void)presentImage:(NSImage *)image; - (void)setText:(NSString *)text; @end @implementation ScatteredAppDelegate @synthesize window; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { srandom((unsigned)time(NULL)); // Set view to be layer-hosting: view.layer = [CALayer layer]; [view setWantsLayer:YES]; CALayer *textContainer = [CALayer layer]; textContainer.anchorPoint = CGPointZero; textContainer.position = CGPointMake(10, 10); textContainer.zPosition = 100; textContainer.backgroundColor = CGColorGetConstantColor(kCGColorBlack); textContainer.borderColor = CGColorGetConstantColor(kCGColorWhite); textContainer.borderWidth = 2; textContainer.cornerRadius = 15; textContainer.shadowOpacity = 0.5f; [view.layer addSublayer:textContainer]; textLayer = [CATextLayer layer]; textLayer.anchorPoint = CGPointZero; textLayer.position = CGPointMake(10, 6); textLayer.zPosition = 100; textLayer.fontSize = 24; textLayer.foregroundColor = CGColorGetConstantColor(kCGColorWhite); [textContainer addSublayer:textLayer]; // Rely on setText: to set the above layers' bounds: [self setText:@"Loading..."]; [self addImagesFromFolderURL: