Archive

Archive for the ‘MonoTouch’ Category

MonoTouch: Simple Web Server

August 18, 2010 Leave a comment

A web server can be a very flexible solution to transferring data from your application. MonoTouch makes it extremely easy to add a web server to your iPhone/iPad application by using the HttpListener class. You can actually implement one with just two methods.

Now this is a very simple example that will just serve up some HTML but you can start from it and extend it to whatever your needs may be. Download the solution file here.

You’ll need to declare two member variables:

private HttpListener listener;
private bool listenerRunning = false;

I used a button click event to both start and stop the server:

partial void startOrStopServer (UIButton sender)
{
	if (!listenerRunning) {
		listener = new HttpListener();
		//Add generic prefix using port 8080
		listener.Prefixes.Add("http://*:8080/");
		
		//Start the server
		listener.Start();
		txtInfo.Text += "Server Started\n";
		btnStart.SetTitle("Stop Server", UIControlState.Normal);
	
		//Begin listening for requests asynchronously
		listener.BeginGetContext(new AsyncCallback(HandleRequest), listener);
	} else {
		//Close the server
		listener.Close();
		listener = null;
		txtInfo.Text += "Server Stoped\n";
		btnStart.SetTitle("Start Server", UIControlState.Normal);
	}
	
	listenerRunning = !listenerRunning;
} 

Request handler method:

private void HandleRequest(IAsyncResult result) {
	if (!listenerRunning) return;
	
	//Get the listener context
	HttpListenerContext context = listener.EndGetContext(result);
	//Start listening for the next request
	listener.BeginGetContext(new AsyncCallback(HandleRequest), listener);
	
	//Update status on the UI thread
	InvokeOnMainThread( delegate {
		txtInfo.Text += "Received request from: " + context.Request.UserHostAddress + "\n";
	});
	
	//Here you can create any response that you want. You can serve text or a file or whatever else you need.
	string response = "<html><head><title>Sample Response</title></head><body>Response from mtouchwebserver.</body></html>";
	byte[] responseBytes = System.Text.Encoding.UTF8.GetBytes(response);
	
	//Set some response information
	context.Response.ContentType = "text/html";
	context.Response.StatusCode = (int)HttpStatusCode.OK;
	context.Response.ContentLength64 = responseBytes.Length;
	
	//Write the response.
	context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
	context.Response.OutputStream.Close();
}

You can run the example solution in the iPhone simulator, start the server, then open a browser and go to http://localhost:8080 to see the results.

Categories: C#, iPhone, MonoTouch Tags: , , ,

MonoTouch: Drawing Rotated Text

July 21, 2010 3 comments

Drawing Rotated Text

I’m taking a break from reading the Professional iPhone Programming with MonoTouch and .NET/C# book (which is awesome by the way) so I decided to write a little tutorial on drawing rotated text.

You can download the MonoDevelop solution here.

There are two drawing methods in the solution, one that shows you how to draw vertical text and one that shows you how to draw rotated text in a circle. Both use the CGAffineTransform object and are pretty similar, but I also show you how to measure a string’s width in the vertical text function.

Let’s take a look at the DrawRotatedText function first:

public static UIImage DrawRotatedText(string text, int width, int height) 
{
	float centerX = width / 2;
	float centerY = height / 2;
	
	//Create the graphics context
	CGBitmapContext ctx = new CGBitmapContext(IntPtr.Zero, width, height, 8, 4 * width, 
		CGColorSpace.CreateDeviceRGB(), CGImageAlphaInfo.PremultipliedFirst);
			
	//Set the font
	ctx.SelectFont("Arial", 16f, CGTextEncoding.MacRoman);	
	
	//Set the fill color to blue
	ctx.SetRGBFillColor(0f, 0f, 1f, 1f);

	//Set the drawing mode 
	ctx.SetTextDrawingMode(CGTextDrawingMode.Fill);
	
	//Draw the text every 22.5 degrees to complete a circle
	for (double angle = 22.5; angle <= 360; angle += 22.5)
	{
		ctx.TextMatrix = CGAffineTransform.MakeRotation((float)DegreesToRadians(angle));
		ctx.ShowTextAtPoint(centerX, centerY, text);
	}
	
	//Return the image
	return UIImage.FromImage(ctx.ToImage());
							 
}

If you’ve read my other MonoTouch drawing posts, you’ll see that the setup is pretty much the same. First create the drawing context, set the font, set the colors, and fill mode. The part that actually does the text rotation is line 22. You set the drawing context’s TextMatrix property equal to a CGAffineTransform object that comes from the static MakeRotation method by passing in a rotation angle in radians. The for loop simply creates a circle of text strings at the center of the image.

Now let’s look at the DrawVerticalText function:

public static UIImage DrawVerticalText(string text, int width, int height)
{
	float centerX = width / 2;
	float centerY = height / 2;
	
	//Create the graphics context
	CGBitmapContext ctx = new CGBitmapContext(IntPtr.Zero, width, height, 8, 4 * width, 
			CGColorSpace.CreateDeviceRGB(), CGImageAlphaInfo.PremultipliedFirst);
	
	//Set the font
	ctx.SelectFont("Arial", 16f, CGTextEncoding.MacRoman);
	
	//Measure the text's width - This involves drawing an invisible string to calculate the X position difference
	float start, end, textWidth;
	
	//Get the texts current position
	start = ctx.TextPosition.X; 
	//Set the drawing mode to invisible
	ctx.SetTextDrawingMode(CGTextDrawingMode.Invisible);
	//Draw the text at the current position
	ctx.ShowText(text);
	//Get the end position
	end = ctx.TextPosition.X;
	//Subtract start from end to get the text's width
	textWidth = end - start;
	
				
	//Set the fill color to blue
	ctx.SetRGBFillColor(0f, 0f, 1f, 1f);

	//Set the drawing mode back to something that will actually draw Fill for example
	ctx.SetTextDrawingMode(CGTextDrawingMode.Fill);
	
	//Set the text rotation to 90 degrees - Vertical from bottom to top.
	ctx.TextMatrix = CGAffineTransform.MakeRotation((float)DegreesToRadians(90));
	//Draw the text at the center of the image.
	ctx.ShowTextAtPoint(centerX - 5, centerY - (textWidth / 2), text);
	
	//Set the text rotation to 270 degrees - Vertical from top to bottom.
	ctx.TextMatrix = CGAffineTransform.MakeRotation((float)DegreesToRadians(270));
	//Draw the text as the center of the image.
	ctx.ShowTextAtPoint(centerX + 5, centerY + (textWidth / 2), text);
	
	//Return the image
	return UIImage.FromImage(ctx.ToImage());
}

So again this looks very similar, to get vertical text you just need to set the rotation angle to 90 degrees for bottom to top text or 270 degrees for top to bottom text.

The function will also center the text in the middle of the image. To do this you need to know what the width of the text will be. There is no Graphics.MeasureString function so you need to do it the Quartz 2d way which involves getting the current text position, setting the draw mode to invisible, drawing the string, getting the end text position, then subtracting the starting position from the end position. Now you can do some simple math to center your text something like (width / 2 – (textWidth / 2), remember to adjust your calculations when you do rotations because you won’t be dealing with just the X coordinate at that point and you may not be drawing from left to right.

Now go add some crazy rotating text to your MonoTouch apps. :-)

Categories: C#, iPhone, MonoTouch

Quick Tip: Simple HTTP Post Using Monotouch

July 19, 2010 Leave a comment

I’ve decided to start a quick tip series on this blog. I’ll try to post some useful code snippets along with some tips and tricks that I’ve learned throughout the years.

This first quick tip shows you how to do a simple HTTP Post in MonoTouch.

You can download the example solution here.

public static string HttpPost(string url, string parameters) 
{
	try
	{
		//Create a WebRequest
		WebRequest req = WebRequest.Create(url);

		//Set the content type and method
		req.ContentType = "application/x-www-form-urlencoded";
		req.Method = "POST";

		//Get the total size of the post parameters and set the content length
		byte [] bytes = System.Text.Encoding.UTF8.GetBytes(parameters);
		req.ContentLength = bytes.Length;

		//Write the data to the request stream
		Stream os = req.GetRequestStream ();
		os.Write (bytes, 0, bytes.Length); 
		os.Close ();

		//Get the response
		WebResponse resp = req.GetResponse();
		if (resp== null) return null;

		//Get the response stream and read the response
		StreamReader sr = new StreamReader(resp.GetResponseStream());			
		string result = sr.ReadToEnd().Trim();
		
		//Close the streams
		sr.Close();
		resp.Close();
		
		return result; 
	}
	catch
	{
		//Epic fail...
		return null;
	}
}

The download also includes a sample PHP page that you can use for testing the POST.

Categories: C#, iPhone, MonoTouch, Quick Tips

MonoTouch: Drawing a pie chart.

July 15, 2010 Leave a comment

Well I lagged a little on this one but here is the continuation of my drawing with MonoTouch tutorials. This one demonstrates how to draw a simple pie chart. You might want to read the previous two articles on drawing with MonoTouch before diving into this one. I just extended the existing drawing app so you download the updated source here to see all the examples.

I tried to make the function as generic as possible to give you the most flexibility.

This is the function for drawing a pie chart:

private UIImage makePieChartImage (int width, int height, float percentage, CGColor baseColor, CGColor topColor)
{
	//Create the CGBitmapContext object
	CGBitmapContext ctx = new CGBitmapContext (IntPtr.Zero, width, height, 8, 4 * width, CGColorSpace.CreateDeviceRGB (), CGImageAlphaInfo.PremultipliedFirst);
	
	//Create two CGPath objects, one for each slice of the pie
	CGPath path1 = new CGPath ();
	CGPath path2 = new CGPath ();
	
	//There are 2 pi radians in a full circle
	//Note that I will make the arc go backwards.
	float twopi = (2f * (float)Math.PI) * -1f;
	
	//Calculate the angle for the first slice
	float angleTop = twopi * percentage;
	
	
	//Calculate the arc start points, center of the circle
	float x = width / 2;
	float y = height / 2;
	
	//Set the radius
	float radius = x;
	
	//Add the first arc path from 0 to first angle
	path1.AddArc (x, y, radius, 0, angleTop, true);
	//Add a line path back to the center of the circle to create a slice
	path1.CGPathAddLineToPoint (x, y);
	
	//Draw the first slice
	ctx.SetFillColorWithColor (topColor);
	ctx.AddPath (path1);
	ctx.DrawPath (CGPathDrawingMode.Fill);
	
	//Add the second arc path from first angle to full circle
	path2.AddArc (x, y, radius, angleTop, twopi, true);
	//Add a line path back to the center of the circle to create a slice
	path2.CGPathAddLineToPoint (x, y);
	
	//Draw the second slice
	ctx.SetFillColorWithColor (baseColor);
	ctx.AddPath (path2);
	ctx.DrawPath (CGPathDrawingMode.Fill);
	
	//return a UIImage object
	return UIImage.FromImage (ctx.ToImage ());
}

There’s a lot of stuff going on here so lets break it down:
Line 4 creates our drawing context.

Lines 7-8 declare two CGPath objects, one for each slice of the pie. Ideally your function would be dynamic enough to draw more than just two slices but I’ll leave that up to you. :-)

Line 12 calculates 2 pi radians (360 degrees, full circumference of a circle.)

Line 15 calculates the angle for the first slice’s percentage. (Remember that your slices need to add up to 2 pi radians if you do extend the method to support more than two slices.)

Lines 18-19 calculate the center of the circle based on the dimensions passed in.

Line 22 sets the radius.

Line 25 creates the first arc from angle 0 to the first percentage calculated, the last parameter specifies if the arc should be drawn clockwise or not.

Line 26 draws a line back to the center of the circle from the endpoint of the first arc, this creates the first slice.

Line 30 sets the fill color for the slice.
Line 31 adds the path to our graphics context.
Line 32 draws the path using the Fill mode.

Lines 34 – 42 do the same thing but for the second slice.

Line 45 returns the pie chart as a UIImage.

As you can see this is a pretty simple function that can be used as a foundation for a more robust routine. I suggest you try to modify this function by creating a Slice class that contains all the information about your pie chart slices then change the drawing function to use the Slice objects to draw your pie chart. I’ll cover drawing a bar graph in my next drawing tutorial (I promise it won’t take 8 months this time.)

Categories: iPhone, MonoTouch

MonoTouch: Drawing custom progress bars.

October 16, 2009 2 comments
MonoTouch Progress Bar

MonoTouch Progress Bar

Here is a simple MonoTouch app that demonstrates how to use Quartz2D to draw custom progress bars.  You can download the MonoDevelop project here.

This app shows how to draw a simple two color progress bar using alpha transparency and a simple two color gradient progress bar.  There are sliders that let you control the colors, transparency level, and progress percentage.  The code uses the CGBitmapContext class to create an image and loads it into UIImageView.

This is the function to create a basic progress bar:

private UIImage makeProgressImage(int width, int height, float progress, CGColor baseColor, CGColor topColor)
{
   //Create a CGBitmapContext object
   CGBitmapContext ctx = new CGBitmapContext(IntPtr.Zero, width, height, 8, 4 * width, CGColorSpace.CreateDeviceRGB(), CGImageAlphaInfo.PremultipliedFirst);

   //Draw a rectangle with the base color
   ctx.SetFillColorWithColor(baseColor);
   ctx.FillRect(new RectangleF(0,0, width, height));

   //Calculate the width of the 2nd rectangle based on the progress
   float percentWidth = width * progress;

   //Draw the second rectangle with the top color
   ctx.SetFillColorWithColor(topColor);
   ctx.FillRect(new RectangleF(0, 0, percentWidth, height));

   //return a UIImage object
   return UIImage.FromImage(ctx.ToImage());
}

This is the function to create a gradient progress bar:

private UIImage makeGradientProgressImage(int width, int height, float progress, float[] components, float[] locations)
{
   //Create a CGBitmapContext object
   CGBitmapContext ctx = new CGBitmapContext(IntPtr.Zero, width, height, 8, 4 * width, CGColorSpace.CreateDeviceRGB(), CGImageAlphaInfo.PremultipliedFirst);

   //Calculate the width of the rectangle based on the progress
   float percentWidth = width * progress;

   //Create a gradient object
   CGGradient gradient = new CGGradient(CGColorSpace.CreateDeviceRGB(), components, locations);

   //Draw a linear gradient to represent the progress bar
   ctx.DrawLinearGradient(gradient, new PointF(0, 0), new PointF(percentWidth, 0), CGGradientDrawingOptions.DrawsBeforeStartLocation);

   //return a UIImage object
   return UIImage.FromImage(ctx.ToImage());
}

Note that these functions are fairly generic and you should be able to reuse them in any of your applications. See the MonoDevelop project for examples on how to use them.  They are also very simple and can be extended to draw “prettier” progress bars without too much effort.  I’ll cover drawing pie charts in my next post.

Categories: C#, iPhone, MonoTouch

Drawing with MonoTouch.

October 2, 2009 6 comments

Here’s a simple example on using Quartz 2D with MonoTouch.

First you need to create a CGBitmapContext object:

int width = 100;
int height = 100;
CGBitmapContext ctx = new CGBitmapContext(IntPtr.Zero, width, height, 8, 4 * width, CGColorSpace.CreateDeviceRGB(), CGImageAlphaInfo.PremultipliedFirst);

Then set some color settings such as the fill and stroke colors:

CGColor red = new CGColor(1f, 0f, 0f, 1f);
CGColor black = new CGColor(0f, 0f, 0f, 1f);
ctx.SetFillColorWithColor(red);
ctx.SetStrokeColorWithColor(black);

Now you can start drawing:

//Draw an ellipse
ctx.FillEllipseInRect(new RectangleF(0, 0, width, height));

//Draw a rectangle inside the ellipse
ctx.SetFillColorWithColor(black);
ctx.FillRect(new RectangleF(width / 4, height / 4, width / 2, height / 2));

Draw some text:

ctx.SetFillColorWithColor(red);
ctx.SelectFont("Arial", 12f, CGTextEncoding.MacRoman);
ctx.ShowTextAtPoint(width / 2, height / 2, "Hi!");

Once you are done drawing you can save your image or display it in a UIImageView using the ToImage() method:

//Show the image in a UIImageView:
myUIImageView.Image = UIImage.FromImage(ctx.ToImage());

//Save your image to file:
UIImage toSave = UIImage.FromImage(ctx.ToImage());
NSError err = new NSError();
toSave.AsJPEG().Save(Path.Combine(Environment.GetFolderPath (Environment.SpecialFolder.Personal), "myimage.jpg"), true, out err);

That should get you on your way to drawing some basic images with MonoTouch. I’ll cover some more advanced techniques in my next post.

Categories: iPhone, MonoTouch Tags: , ,
Follow

Get every new post delivered to your Inbox.