Friday, 23 July 2010

Drawing on Maps with MonoTouch

iOS4 introduced new features like MKOverlay to help draw lines/routes and shapes/polygons on the MKMapView control, however it has always been possible to add these features to maps in iOS3.

Two (Objective-C) examples of displaying geometric shapes on MKMapView in iOS3 are:
...it is these examples that I've ported to MonoTouch (as a Universal app: iPhone and iPad). You can grab the code from github project MapStuff and see some screenshots below:

I put together a class diagram to try and explain how they work (the classes shown are from the 2nd example, which allows you to draw your own shape).

Please remember all the hard work here has been done by the original authors. All credit goes to them. Any bugs in the MonoTouch code are mine... let me know if you find any.

iOS4 examples to follow...

Sunday, 18 July 2010

More MonoTouch Machine-translation Madness!

In addition to the recent dodgy Spanish localization, my TweetStation fork now has dodgy French, Japanese, German and Italian translations (courtesy of the Microsoft Translator API that was introduced at MIX10). Here's how they look:



The following two code snippets were added to ngenstrings so that once the text has been extracted from TweetStation, it is automatically translated and written to .strings files ready for inclusion in the correctly-named .lproj folders (this code hasn't been committed to github - but it should be easy to add to your local copy).

add code to the end of MainClass.Main
string[] languages = new string[]{"fr","ja","it","de"};
foreach (var language in languages)
{
   foreach (var table in tables.Values)
   {
      foreach (LocalizedString locstring in table.Values)
      {
         locstring.Value = Translate(locstring.Key, language);
      }
      table.WriteStringsFile(assemblyName, outputFormat, language);
   }
}

add method to MainClass
//http://msdn.microsoft.com/en-us/library/ff512421.aspx
static string Translate (string text, string toLanguageCode)
{
   string appId = "REGISTER_AND_INSERT_YOUR_APPID";
   string translation = text;
   text = text.Replace(" ", "%20").Replace("&", "").Replace("#","%3F");

   string detectUri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=" + appId +
  "&text=" + text + "&from=en&to=" + toLanguageCode;
   Console.WriteLine(detectUri);
   try {
      System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(detectUri);
      System.Net.WebResponse resp = httpWebRequest.GetResponse();
      Stream strm = resp.GetResponseStream();
      StreamReader reader = new System.IO.StreamReader(strm);
      translation = reader.ReadToEnd();
   }
   catch (Exception e)
   {
      Console.Write("Translation failed for " + text + " - " + e.Message);
   }
   return translation;
}

Hopefully that gives you some ideas (or inspiration) on how to increase the market for your apps across the world. Remember that machine-translation is NOT a substitute for a professional human translation, however it can be useful to test your application's ability to handle and display different languages (eg. the size of the strings, etc).

Friday, 16 July 2010

TwitEstaçion: MonoTouch TweetStation en español

If you are a MonoTouch developer then you should already be familiar with the two subjects of this post:
It just so happens that Chapter 12 - Localizing for an International Audience of the book introduces a small utility called ngenstrings that helps you to translate your application into other languages. Today I updated ngenstrings to use the latest Mono.Cecil version, and to test it out I decided to have a go at localizing TweetStation into Spanish. You can download the Localizable.strings file that was created (and translated courtesy of Bing). Here's a screenshot showing where it fits into the solution:
...and here are a couple of screenshots showing TwitEstaçion in action ;-)

NOTE: Miguel had already made a good start building an internationalized app - many of his strings were wrapped in a Locale.GetText() method which was easy for me to work with. None of his code needed to change except for Locale.Get() and Locale.Format() to add NSBundle.MainBundle.LocalizedString(str,"");
NOTE2: this was a MACHINE TRANSLATION - of course you would arrange for a real person to translate your apps before taking them to the AppStore!
NOTE3: I have not translated 100% of Miguel's app - this is for demonstration purposes at the moment.
NOTE4: It's called TwitEstaçion because "TweetEstaçion" is too long for the iPhone home screen, and gets shortened unreadably. I don't speak Spanish so who knows if that makes any sense at all!

UPDATE: a few more screenshots... (again, apologies for the machine translation:)
UPDATE2: localized code forked from TweetStation main now available on github.

Friday, 9 July 2010

MonoTouch port of TDBadgedCell

I recently wanted to add an 'item count' to a UITableView in one of my iPhone/iPad projects and thought it would be nice to match the grey/encircled 'badge' used in the Mail application.

Happily,  I found (via The Unofficial Apple Weblog) that Tim Davies had the same idea and already done the hard work, albeit in Objective-C. Tim's code for TDBadgedCell is on github (you can help him out and donate, too), as is the MonoTouch/C# port: TDBadgedCellSharp. Both produce the same output (shown below)

The important stuff (TDBadgeView and TDBadgeCell) is in TDBadgedCell.cs - the rest of the project is purely for demonstration purposes.

Here's a very simple example of how to use the badged cell (warning: doesn't show DequeueReusableCell which you would normally use in the GetCell method)...

public override UITableViewCell GetCell 
   (UITableView tableView, NSIndexPath indexPath)
{
   TDBadgedCell cell = new TDBadgedCell (UITableViewCellStyle.Subtitle, "Cell");
   cell.TextLabel.Text = contents[indexPath.Row].Title;
   cell.TextLabel.Font = UIFont.BoldSystemFontOfSize (14);

   cell.DetailTextLabel.Text = contents[indexPath.Row].Detail;
   cell.DetailTextLabel.Font = UIFont.SystemFontOfSize (13);

   cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
   cell.BadgeNumber = Convert.ToInt32 (contents[indexPath.Row].Badge);

   if (indexPath.Row == 1)
      cell.BadgeColor = UIColor.FromRGBA (1.000f, 0.397f, 0.419f, 1.000f);
   if (indexPath.Row == 2)
      cell.BadgeColor = UIColor.FromWhiteAlpha (0.783f, 1.000f);
   return cell;
}

Thanks Tim!

..and finally, if you didn't notice the cover at the top of this page or seen the tweets, "my" book (and Wally, Chris, Martin & Rory's :) is now available from Amazon (and other locations, in paper or PDF)!