Search code examples
c#iosxamarin.iosxamarincagradientlayer

Creating a UIView subclass that uses a CAGradientLayer as its layer


I want to port this to C#.

I don't know how I should convert this:

@property (nonatomic, strong, readonly) CAGradientLayer *layer;

The layer is the default layer for the UIView. Xamarin already has a Layer property. How do I overwrite this? Do I need to overwrite it?

I also tried it with

public CAGradientLayer layer { [Export ("Layer")] get; [Export ("Layer:")] set; }

but the app crashes (System.Reflection.TargetInvocationException - NullReferenceException when dequeuing the cell) if I want to set the colors of the layer. Furthermore it should be readonly.

Then I saw in the documentation how it could be converted:

public class BlueView : UIView
{
    [Export ("layerClass")]
    public static Class GetLayerClass ()
    {
        return new Class (typeof (BlueLayer));
    }

    public override void Draw (RectangleF rect)
    {
        // Do nothing, the Layer will do all the drawing
    }
}

public class BlueLayer : CALayer
{
    public override void DrawInContext (CGContext ctx)
    {
        ctx.SetFillColor (0, 0, 1, 1);
        ctx.FillRect (Bounds);
    }
}

This doesn't help me because I need something like SetFillColors so that I can use CGColor[] array. But there is no such function.

How do I create my UIView with my custom CAGradientLayer in C# with Monotouch?


Solution

  • This wonderful post (iOS Programming Recipe 20: Using CAGradientLayer In A Custom View) pointed me in the right direction:

    using System;
    using System.Drawing;
    using MonoTouch.Foundation;
    using MonoTouch.UIKit;
    using MonoTouch.CoreAnimation;
    using MonoTouch.CoreGraphics;
    using MonoTouch.ObjCRuntime;
    
    namespace SampleApp
    {
        public class GradientView : UIView
        {
    //      public new CAGradientLayer Layer { get; private set; }
            private CAGradientLayer gradientLayer {
                get { return (CAGradientLayer)this.Layer; }
            }
    
            public GradientView ()
            {
            }
    
    
            [Export ("layerClass")]
            public static Class LayerClass ()
            {
                return new Class (typeof(CAGradientLayer));
            }
    
            public void setColors(CGColor[] colors){
                this.gradientLayer.Colors = colors;
            }
    
    //      public override void Draw (RectangleF rect)
    //      {
    //          // Do nothing, the Layer will do all the drawing
    //      }
        }
    }
    

    And here I create and set up my background view:

    GradientView background = new GradientView ();
    background.setColors (new CGColor[] {
        UIColor.FromRGB (18,200,45).CGColor,
        UIColor.White.CGColor,
        UIColor.White.CGColor
    });
    

    Now it seems to work. Using a custom property (inclusive cast) and a separate method did the trick. Of course you can write a full accessor. This was a simple test.