Search code examples
iosipadxamarin.ios

Programmatically draw rectangles with MonoTouch


I am trying to learn more about MonoTouch and so I tried out drawing with Quartz2D. I want to create an example, where I draw n-rectangles programmatically. The problem is that only the first one is drawn. I think that the second one is deleted/cleared/covered by the first one.

Here is my code:

SingleViewMTViewController.cs

public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        PointF locationOne = new PointF (5, 5);
        PointF locationTwo = new PointF (5, 100);
        SizeF size = new SizeF (120, 40);

        DraggableRectangle tView = new DraggableRectangle (locationOne, size, UIColor.Yellow);
        DraggableRectangle tView2 = new DraggableRectangle (locationTwo, size, UIColor.Brown);

        DraggableRectangle[] views = new DraggableRectangle[2];
        views [0] = tView;
        views [1] = tView2;

        View.AddSubviews (views);
    }

DraggableRectangle.cs

public class DraggableRectangle : UIView
{
    private CGPath path;
    private PointF _targetLocation;
    private SizeF _size;
    private UIColor _fillColor = UIColor.Brown;

    public DraggableRectangle (PointF targetLocation, SizeF size)
    {
        _targetLocation = targetLocation;
        _size = size;

        RectangleF frameRect = new RectangleF (_targetLocation.X, _targetLocation.Y, _size.Width, _size.Height);
        this.Frame = frameRect;
        this.BackgroundColor = UIColor.Clear; //without this, nothing is drawn
    }

    public DraggableRectangle (PointF targetLocation, SizeF size, UIColor fillColor):this(targetLocation,size)
    {
        _fillColor = fillColor;
    }

    public override void Draw (RectangleF rect)
    {
        //base.Draw (rect);
        //works without base-call?

        //get graphics context
        using (CGContext gctx = UIGraphics.GetCurrentContext ()) {

            //set up drawing attributes
            _fillColor.SetFill ();

            //create geometry
            path = new CGPath ();

            path.AddRect (new RectangleF (_targetLocation.X, _targetLocation.Y, _size.Width, _size.Height));

            path.CloseSubpath ();

            //add geometry to graphics context and draw it
            gctx.AddPath (path);        
            gctx.DrawPath (CGPathDrawingMode.FillStroke);   
        }       
    }

Is there a better way to draw independent rectangles with MonoTouch? Or could please someone explain, what I am doing wrong?

UPDATE: Thats btw. the best output I can achieve, but thats just not correct for "Yellow" and "Brown" http://www.bilder-upload.eu/show.php?file=81bfea-1329755225.png http://www.bilder-upload.eu/show.php?file=81bfea-1329755225.png


Solution

  • Actually, both of your rectangles are drawn. The problem is your _targetLocation.Y value. You are setting the same Y value for both your view's Frame and its rectangle to be drawn in its Draw method.

    So basically, your rectangle is drawn outside the bounds of the view. Your "brown" view's height is 40pt, while its rectangle is drawn at Y=100 (below its visible portion).

    You have to differentiate these values, since a view's location is always relative to its parent's coordinates.

    Edit: a pseudo-code example.

    The following line:

    path.AddRect (new RectangleF (_targetLocation.X, _targetLocation.Y, _size.Width, _size.Height));
    

    Should be something like:

        path.AddRect (new RectangleF ({Frame.Width >= something >= 0}, 
    {Frame.Height >= something >= 0}, width, height);
    

    Edit #2:

    If I change the rect of the path, with the following:

    path.AddRect (new RectangleF (0f, 0f, _size.Width, _size.Height));
    

    Here is what I get...

    Two rects