See Also: CALayer Members
CALayers hold the image content that is rendered into the screen. They encapsulate position, styling, size and transformation components. They also implement the CAMediaTiming methods which allows them to participate in animations.
There are several subclasses of CALayer that developers can use: MonoTouch.CoreAnimation.CAEmitterLayer, MonoTouch.CoreAnimation.CAGradientLayer, MonoTouch.CoreAnimation.CAEAGLLayer/CAOpenGLLayer, MonoTouch.CoreAnimation.CAReplicatorLayer, MonoTouch.CoreAnimation.CAScrollLayer, MonoTouch.CoreAnimation.CAShapeLayer, MonoTouch.CoreAnimation.CATextLayer, MonoTouch.CoreAnimation.CATiledLayer, MonoTouch.CoreAnimation.CATransformLayer and MonoTouch.CoreAnimation.QCCompositionLayer.
There are three ways of providing content to a layer: subclassing the layer class and overriding the draw methods, using a layer delegate to implement the drawing or assigning a static image to the layer.
To set the contents of the layer with a static image or from one of the rendering approaches, app devs must assign a MonoTouch.CoreGraphics.CGImage to the CALayer.Contents property. For static content, they can just assign this property and the changes will be reflected directly.
If you choose to subclass the CALayer class, you can either sublcass the CALayer.Display() method which is then requires to set the CALayer.Contents property or you can override the CALayerDelegate.DrawInContext(MonoTouch.CoreGraphics.CGContext) method which provides you with a graphics context that you can use to render into the display.
C# Example
// Overriding DrawInContext public class DemoLayer : CALayer { public override void DrawInContext (CGContext context) { base.DrawInContext (context); // Fill in circle context.SetFillColor (Color); context.SetShadowWithColor (SizeF.Empty, 10.0f, glowColor); context.EOFillPath(); } } // Overriding Display public class DemoLayer2 : CALayer { CGImage image = UIImage.FromBundle ("demo.png").CGImage; public override void Display () { Contents = image; } } ]></code> </example> <format type="text/html"> <h3>Contents by Providing a CALayerDelegate</h3> </format> <para> This approach can be used if the developer does not want to change the class used for their CALayer rendering, and all they need to do is assign the <see cref="P:MonoTouch.CoreAnimation.CALayer.Delegate" /> property to an instance of a subclass of <see cref="T:MonoTouch.CoreAnimation.CALayerDelegate" /> where they either override the <see cref="M:MonoTouch.CoreAnimation.CALayerDelegate.DisplayLayer(MonoTouch.CoreAnimation.CALayer)" /> method in which they must set the <see cref="P:MonoTouch.CoreAnimation.CALayer.Contents" /> property, or they override the <see cref="M:MonoTouch.CoreAnimation.CALayerDelegate.DrawLayer(MonoTouch.CoreAnimation.CALayer,MonoTouch.CoreGraphics.CGContext)" /> method and provide their own rendering code there. </para> <example> <code lang="C#"><![CDATA[ // Overriding DisplayLayer public class DemoLayerDelegate : CALayerDelegate { CGImage image = UIImage.FromBundle ("demo.png").CGImage; public override void DisplayLayer (CALayer layer) { layer.Contents = image; } } // Overriding DrawLayer public class DemoLayerDelegate2 : CALayerDelegate { public override DrawLayer (CALayer layer, CGContext context) { // Fill in circle context.SetFillColor (Color); context.SetShadowWithColor (SizeF.Empty, 10.0f, glowColor); context.EOFillPath(); } } // To use the code: void SetupViews (UIView view, UIView view2) { view.Layer.Delegate = new DemoLayerDelegate (); view2.Layer.Delegate = new DemoLayerDelegate2 (); }
On iOS, every UIView automatically has a CALayer associated with it. When you want to use one of the CALayer subclasses as your UIView's backing layer, you need to add the following code snippet to your class:
C# Example
class MyView : UIView { // // This instructs the runtime that whenever a MyView is created // that it should instantiate a CATiledLayer and assign that to the // UIView.Layer property // [Export ("layerClass")] public static Class LayerClass () { return new Class (typeof (CATiledLayer)); } }
If you want to subclass the CALayer class, you must provide a constructor that takes a CALayer and is annotated with an [Export ("initWithLayer:")] attribute. When you do this, you should also override the CALayer.Clone (CALayer) as these two are used to create copies of your layer state on demand in response to CoreAnimation creating a mirror of your object hierarchy if anyone accesses the CALayer.PresentationLayer property.
C# Example
public class MyLayer : CALayer { UIColor FirstColor, SecondColor; // // Invoked by CoreAnimation if it needs to create a copy of your layer // with a specific state in response to the user fetching the PresentationLayer // property // [Export ("initWithLayer:")] public MyLayer (Mylayer other) : base (layer) { // Do nothing, since we override Clone, but we could // just clone the data here as well if we wanted to. } // // This is the constructor you would use to create your new CALayer public MyLayer (UIColor firstColor, UIColor secondColor) { FirstColor = firstColor; SecondColor = secondColor; } // We must copy our own state here from the original layer public override void Clone (CALayer _other) { MyLayer other = (MyLayer) _other; FirstColor = other.FirstColor; SecondColor = other.SecondColor; } }
On OSX, CALayers are optional. To enable them, you must set the MonoMac.AppKit.NSView.WantsLayer property to true. You can change the layer for an NSView by setting the MonoMac.AppKit.NSView.Layer property.
On OSX, to change the default layer class used for a given NSView, you can override the MonoMac.AppKit.MakeBackingLayer method.