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:
[sourcecode language=”csharp”]
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());
}
[/sourcecode]
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:
[sourcecode language=”csharp”]
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());
}
[/sourcecode]
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. 🙂
Pingback: MonoTouch.Info
Hello,
I find your blog by searching for “ShowTextAtPoint”. We are using a similar method for text output on a graphic context.
But we have the problem that german umlaute are not displayed (they are replaced by other characters).
Unfortunately, we didn´t get any support from novell (neither any answer).
Do you have any idea, if this is a general problem by monotouch classes?
Thanks for any help.
Frank
Hi Frank,
I’m not sure what might be causing your issue but I would go ask in the Xamarin site. They recently took over all support from Novell.