Layer Content

A layer is simply a bitmap, and its contents can be set programmatically or with an image. To set the contents programmatically, you either subclass CALayer or assign a delegate to an instance of CALayer. The delegate then implements drawing routines. (This is how implicit layers work; the view is its layer’s delegate.)

We will discuss drawing to a layer programmatically at the end of this chapter. For now, you’re going to set the contents of the layer using an image file.

In HypnosisView.m, add the following code to the initWithFrame: method:

-​ ​(​i​d​)​i​n​i​t​W​i​t​h​F​r​a​m​e​:​(​C​G​R​e​c​t​)​r​
{​
 ​ ​ ​ ​s​e​l​f​ ​=​ ​[​s​u​p​e​r​ ​i​n​i​t​W​i​t​h​F​r​a​m​e​:​r​]​;​

 ​ ​ ​ ​i​f​ ​(​s​e​l​f​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​s​t​r​i​p​e​C​o​l​o​r​ ​=​ ​[​[​U​I​C​o​l​o​r​ ​l​i​g​h​t​G​r​a​y​C​o​l​o​r​]​ ​r​e​t​a​i​n​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​b​o​x​L​a​y​e​r​ ​=​ ​[​[​C​A​L​a​y​e​r​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​b​o​x​L​a​y​e​r​ ​s​e​t​B​o​u​n​d​s​:​C​G​R​e​c​t​M​a​k​e​(​0​.​0​,​ ​0​.​0​,​ ​8​5​.​0​,​ ​8​5​.​0​)​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​b​o​x​L​a​y​e​r​ ​s​e​t​P​o​s​i​t​i​o​n​:​C​G​P​o​i​n​t​M​a​k​e​(​1​6​0​.​0​,​ ​1​0​0​.​0​)​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​U​I​C​o​l​o​r​ ​*​r​e​d​d​i​s​h​ ​=​ ​[​U​I​C​o​l​o​r​ ​c​o​l​o​r​W​i​t​h​R​e​d​:​1​.​0​ ​g​r​e​e​n​:​0​.​0​ ​b​l​u​e​:​0​.​0​ ​a​l​p​h​a​:​0​.​5​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​C​G​C​o​l​o​r​R​e​f​ ​c​g​R​e​d​d​i​s​h​ ​=​ ​[​r​e​d​d​i​s​h​ ​C​G​C​o​l​o​r​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​b​o​x​L​a​y​e​r​ ​s​e​t​B​a​c​k​g​r​o​u​n​d​C​o​l​o​r​:​c​g​R​e​d​d​i​s​h​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​ ​U​I​I​m​a​g​e​
 ​ ​ ​ ​ ​ ​ ​ ​U​I​I​m​a​g​e​ ​*​l​a​y​e​r​I​m​a​g​e​ ​=​ ​[​U​I​I​m​a​g​e​ ​i​m​a​g​e​N​a​m​e​d​:​@​"​H​y​p​n​o​.​p​n​g​"​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​G​e​t​ ​t​h​e​ ​u​n​d​e​r​l​y​i​n​g​ ​C​G​I​m​a​g​e​
 ​ ​ ​ ​ ​ ​ ​ ​C​G​I​m​a​g​e​R​e​f​ ​i​m​a​g​e​ ​=​ ​[​l​a​y​e​r​I​m​a​g​e​ ​C​G​I​m​a​g​e​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​P​u​t​ ​t​h​e​ ​C​G​I​m​a​g​e​ ​o​n​ ​t​h​e​ ​l​a​y​e​r​
 ​ ​ ​ ​ ​ ​ ​ ​[​b​o​x​L​a​y​e​r​ ​s​e​t​C​o​n​t​e​n​t​s​:​(​i​d​)​i​m​a​g​e​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​I​n​s​e​t​ ​t​h​e​ ​i​m​a​g​e​ ​a​ ​b​i​t​ ​o​n​ ​e​a​c​h​ ​s​i​d​e​
 ​ ​ ​ ​ ​ ​ ​ ​[​b​o​x​L​a​y​e​r​ ​s​e​t​C​o​n​t​e​n​t​s​R​e​c​t​:​C​G​R​e​c​t​M​a​k​e​(​-​0​.​1​,​ ​-​0​.​1​,​ ​1​.​2​,​ ​1​.​2​)​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​L​e​t​ ​t​h​e​ ​i​m​a​g​e​ ​r​e​s​i​z​e​ ​(​w​i​t​h​o​u​t​ ​c​h​a​n​g​i​n​g​ ​t​h​e​ ​a​s​p​e​c​t​ ​r​a​t​i​o​)​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​t​o​ ​f​i​l​l​ ​t​h​e​ ​c​o​n​t​e​n​t​R​e​c​t​
 ​ ​ ​ ​ ​ ​ ​ ​[​b​o​x​L​a​y​e​r​ ​s​e​t​C​o​n​t​e​n​t​s​G​r​a​v​i​t​y​:​k​C​A​G​r​a​v​i​t​y​R​e​s​i​z​e​A​s​p​e​c​t​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​[​[​s​e​l​f​ ​l​a​y​e​r​]​ ​a​d​d​S​u​b​l​a​y​e​r​:​b​o​x​L​a​y​e​r​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​b​o​x​L​a​y​e​r​ ​r​e​l​e​a​s​e​]​;​
 ​ ​ ​ ​}​

 ​ ​ ​ ​r​e​t​u​r​n​ ​s​e​l​f​;​
}​

In this code, we create an image and then get the underlying CGImage to use with Core Graphics drawing. Then we set the image as the layer’s contents and make adjustments for how the contents appear within the layer.

Notice the use of CGImageRef and CGColorRef in this method. Why doesn’t Core Animation use UIImage and UIColor?

The QuartzCore framework (which supplies the classes CALayer and CAAnimation) and Core Graphics framework (which supplies CGImageRef) exist on both iOS and on the Mac. UIKit (where we get UIImage and anything else prefixed with UI) only exists in iOS. To maintain its portability, QuartzCore must use CGImageRef instead of UIImage. Fortunately, UIKit objects have methods to easily access their Core Graphics counterparts, like UIImage’s CGImage method you used in the previous code.

Build and run the application. Now your layer has an image for its contents, as shown in Figure 22.5.

Figure 22.5  Layer with image

Layer with image

Because layers exist in a hierarchy, they can have sublayers, and each layer has a pointer back to its parent layer called superlayer. When a layer is composited to the screen, it is copied to the screen, and then each sublayer is composited atop it. Therefore, a layer always draws on top of its superlayer.

In a view hierarchy, sibling views (views with the same parent) will typically not have overlapping bounds. For instance, imagine a view with two subviews that are buttons. What would be the point of them overlapping and obscuring each other? It would only confuse and frustrate the user trying to tap one or the other.

The layer hierarchy, however, is a different story. Siblings are far more likely to overlap because layers are about visual effects and drawing, not user interaction. Which sibling is composited over the other? Each layer has a property called zPosition. If two layers are siblings and they overlap, then the layer with the higher zPosition is composited on top of the layer with the lower zPosition. (A sublayer always draws on top of its superlayer, regardless of zPosition.)

A layer’s zPosition defaults to 0 and can be set to a negative value.

 ​ ​ ​ ​[​u​n​d​e​r​L​a​y​e​r​ ​s​e​t​Z​P​o​s​i​t​i​o​n​:​-​5​]​;​
 ​ ​ ​ ​[​o​v​e​r​L​a​y​e​r​ ​s​e​t​Z​P​o​s​i​t​i​o​n​:​5​]​;​
 ​ ​ ​ ​[​p​a​r​e​n​t​L​a​y​e​r​ ​a​d​d​S​u​b​l​a​y​e​r​:​u​n​d​e​r​L​a​y​e​r​]​;​
 ​ ​ ​ ​[​p​a​r​e​n​t​L​a​y​e​r​ ​a​d​d​S​u​b​l​a​y​e​r​:​o​v​e​r​L​a​y​e​r​]​;​

 ​ ​ ​ ​/​/​ ​o​v​e​r​L​a​y​e​r​ ​i​s​ ​c​o​m​p​o​s​i​t​e​d​ ​o​n​ ​t​o​p​ ​o​f​ ​u​n​d​e​r​L​a​y​e​r​!​

When the Z-axis is discussed, some developers imagine that perspective is applied, and they expect a layer to appear larger as its zPosition increases. However, Core Animation layers are presented orthographically; they do not appear as different sizes based on their zPositions.

Figure 22.6  Perspective vs. Orthographic

Perspective vs. Orthographic

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.252.56