CoreGraphics allows you to do custom drawing on the iPhone. MonoTouch exposes this in the namespace MonoTouch.CoreGraphics. This allows you to do all sorts of custom drawing. Here I’ll present an introductory example that shows how to draw a triangle in a custom view along with determining if the triangle was touched. Even as drawing complexity increases, you’ll find the code to be quite similar in general, just that there will be more of it.
For the example I created a new MonoTouch window-based app and added a new ViewController from the ViewController with View template, naming it DrawingViewController.xib. I then added a class called DrawingView, subclassed from UIView, that I wired up in Interface Builder to be the view under DrawingViewController. After that I decorated the DrawingView class with the Resigister attribute so it will be available for the Objective-C runtime. As it’s being created from the xib, I also included the constructor that takes an IntPtr. See some of the tutorials on the monotouch wiki or the articles aggregated at monotouch.info if you need to review the details of how to wire things up.
With the DrawingView class in place, you can override the Draw (RectangleF rect) method to implement custom drawing. You implement what you want to draw in the Draw method and CocoaTouch will call it at runtime during event loop processing. To draw you need to:
- Get a graphics context
- Set up drawing attributes
- Create some geometry from drawing primitives
- Call a Draw or Stroke method
Here’s a simple example that draws a rectangle and fills it with a color:
using System; using MonoTouch.UIKit; using System.Drawing; using MonoTouch.CoreGraphics; using MonoTouch.Foundation; namespace CoreGraphicsDemo { [Register("DrawingView")] public class DrawingView : UIView { CGPath path; public DrawingView (IntPtr p) : base(p) { } public override void Draw (RectangleF rect) { base.Draw (rect); //get graphics context CGContext gctx = UIGraphics.GetCurrentContext (); //set up drawing attributes gctx.SetLineWidth(4); UIColor.Purple.SetFill (); UIColor.Black.SetStroke (); //create geometry path = new CGPath (); path.AddLines(new PointF[]{ new PointF(100,200), new PointF(160,100), new PointF(220,200)}); path.CloseSubpath(); //add geometry to graphics context and draw it gctx.AddPath(path); gctx.DrawPath(CGPathDrawingMode.FillStroke); } ...
To respond to touches on the triangle you can override TouchesBegan and make use of the LocationInView method on UITouch like this:
public override void TouchesBegan (NSSet touches, UIEvent evt) { base.TouchesBegan (touches, evt); UITouch touch = touches.AnyObject as UITouch; if(touch != null) { PointF pt = touch.LocationInView(this); if(path.ContainsPoint(pt, true)) { Console.WriteLine("Hit {0}", pt.ToString()); } else { Console.WriteLine("No Hit {0}", pt.ToString()); } } }

Hi —
First, thanks for posting this tutorial. I am new to MonoTouch development and have done some of the basic tutorials, but I am unclear exactly how to wire up the DrawingView class so it is the view under DrawingViewController. I can’t seem to see a reference to DrawingView in IB at all. DrawingView should be in its own class file, right?
Any help you could provide would be greatly appreciated.
Thanks.
Jeremy Schwartz
take a look at the sample project I created here: http://github.com/mikebluestein/iBabySmash
hmm I am still unclear on how to procede exactly to wired up the DrawingView class in Interface Builder to be under DrawingViewController. I am sorry if I seem lazy but I have a hard time following your book since I am a newbie and have a hard time transposing your tutorials with the new version of xcode.
Best Regards,
Thank you,
Sonia
Thank’s for the tutorial sir,
I am trying signature concept in monotouch can you help me with this,Any suggestions or any idea.
I think I’d use OpenGL for this use case. There’s a paint sample here that should get you started: https://github.com/migueldeicaza/monotouch-samples/tree/master/GLPaint-GV
Thanks for the tutorial,
But when i run the code in monodevelop i get the following error.
Error connecting stdout and stderr (127.0.0.1:10001)
Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
open$UNIX2003 called from function _ZN4llvm12MemoryBuffer7getFileEPKcPSsx in image libLLVMContainer.dylib.
Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
fstat$INODE64 called from function _ZN4llvm12MemoryBuffer7getFileEPKcPSsx in image libLLVMContainer.dylib.
Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
mmap$UNIX2003 called from function _ZN4llvm3sys4Path14MapInFilePagesEiy in image libLLVMContainer.dylib.
Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
close$UNIX2003 called from function _ZN4llvm12MemoryBuffer7getFileEPKcPSsx in image libLLVMContainer.dylib.
Does this caused any native library in monodevelop?
Please help.
Thanks,
That is a wonderful tutorial.
Can you provide me how to save that as image or any idea would be appreciated.
Please…
Hai,
Thank’s for the tutorial,
I am new to monotouch.
I have created a signature concept using mouse touches began event.
When i move the cursor slowly the coordinates are perfectly highligting,but when the cursor movement is fast there is a large gap between Consequent coordinates.Please help..
The code
var currentPoint = new PointF();
var lastPoint = new PointF();
UITouch touch = touches.AnyObject as UITouch;
currentPoint = touch.LocationInView(this);
currentPoint.Y -=7;
currentPoint.Y -= 1;
currentPoint.X -=1;
UIGraphics.BeginImageContext(this.Frame.Size);
CGContext cont = UIGraphics.GetCurrentContext();
if (this.Image != null)
{
cont.TranslateCTM(0f, this.Frame.Size.Height);
cont.ScaleCTM(1.0f, -1.0f);
cont.DrawImage(new RectangleF(0, 0, this.Frame.Size.Width, this.Frame.Size.Height), this.Image.CGImage);
cont.ScaleCTM(1.0f, -1.0f);
cont.TranslateCTM(0f, -this.Frame.Size.Height);
}
cont.SetLineCap(CGLineCap.Round);
cont.SetLineWidth(3f);
cont.SetRGBStrokeColor(0f,0f,0f,1.00f);
cont.BeginPath();
cont.MoveTo(currentPoint.X, currentPoint.Y);
cont.AddLineToPoint(currentPoint.X,currentPoint.Y);
cont.AddLineToPoint(currentPoint.X,currentPoint.Y);
Console.WriteLine(“CurrentPoint: ” + currentPoint.X + “:” + currentPoint.Y.ToString());
Console.WriteLine(“LastPoint: ” + lastPoint.X + “:” + lastPoint.Y.ToString());
cont.DrawPath(CGPathDrawingMode.Stroke);
this.Image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
lastPoint = currentPoint;
NSError err = new NSError();
string img_path=”path”;
this.Image.AsJPEG().Save(img_path,true, out err);
you should try the given code. at Line 13 in the first segment of code, path is declared to be global in the class. at line 32, it is recreated everytime the Draw method gets hit. that causes the large gap you are talking about. if you comment out the line 32, you get the thing you want. in short, the lines added to the path has to be accumulated, i guess.
Thank you for the reply,
I have cleared the signature concept and it is fine.
now i am including camera concept using Avfoundation, how can i save the image?
any idea or suggestion would be appreciated.
There’s a wiki post about storing files here: http://wiki.ios.xamarin.com/HowTo/Files/HowTo%3a_Store_Files
Thank you,
Now i can save image in the device path.
I am capturing image using AVFoundation Camera concept.
My camera is in landscape mode.
How can i change it to potrait mode.
any help would be appreciated.