Thursday 30 September 2010

MonoTouch... CATiledLayer example (like DeepZoom/multi-scale-image)

UPDATE 2-Oct-02: Thanks to Miguel's assistance the NPhotoScroller code on github is now working!

The CORRECT port of this Objective-C snippet...

+ (Class)layerClass {
  return [CATiledLayer class];
} this c# (requires using MonoTouch.ObjCRuntime;)

[Export ("layerClass")]
public static Class LayerClass () {
  return new Class (typeof (CATiledLayer));

and not the dodgy hack I came up with below...

Original Post:
Normally code posted on this blog actually works (or close to it...) but today I have a half-done port of an Objective-C sample that I just can't seem to finish off :-(

The idea was to port Apple's PhotoScroller sample, which demonstrates how to use the CATiledLayer, to MonoTouch.

The work-in-progress is on github: NPhotoScroller*... however it isn't quite finished and I'm hoping someone will point out what is missing.

If you download the sample (and grab the images from Apple), the my MonoTouch port looks like this:

It seems to be working, since the image is being successfully drawn using tiles BUT there are too many tiles for this zoom level. It should look like the image below (ie. 4 tiles) but I can only get that effect by hardcoding TilingView.cs::line 96 to a specific zoom level of 0.125

Using a different hardcoded zoom level of 0.25 results in this output, so the tiles are 'definitely kinda working'...

The problem? Zooming is totally broken - any attempt to pinch/zoom on these images breaks. TilingView.cs::line 95 ALWAYS returns a scale of 1 - it never changes. ImageScrollView.cs::line 157 this.ZoomScale = this.MinimumZoomScale seems to have no effect: no matter what the MinimumZoomScale is (eg. 0.08), ZoomScale is always 1 and the context.GetCTM() CGAffineTransform never reflects a change in zoom level.

If you switch from 'tiled' to 'whole' images (PhotoViewController.cs::line 63 useTiledImage = false;) then zooming works perfectly (if greedily from a memory perspective). I would love to hear any suggestions!!

Aside: I did have one minor issue with the port... what to do with this code in TilingView.m

+ (Class)layerClass {
return [CATiledLayer class];

It's been ported as the following in TilingView.cs but I could be way off base...

private CATiledLayer __layer;
public override CALayer Layer {get
{ // set in ctor
return __layer;


* NOTE: If you download the sample from github, you MUST also download Apple's original sample to get their test image files.

Saturday 25 September 2010

MonoTouch meet WindowsPhone7

This is a very basic example of how you can share data and code between the iPhone platform (using MonoTouch) and recently RTM'd Windows Phone 7.

iPhone and Windows Phone 7 screenshots : click to enlarge

The code is available on github... notice that the source data (restaurants.xml file) and class file (Objects.cs) are identical on both platforms, as is the XmlSerialization code that parses the data into memory for display.

You will see there is a lot more 'user code' in the MonoTouch project for iPhone - this is due to the laborious way that UITableViews must be coded*; whereas the WP7's Silverlight heritage allows some very neat databinding scenarios.

* the excellent MonoTouch.Dialog project significantly reduces this code overhead on MonoTouch - definitely give it a try! I just need to put the MonoDroid version together... :-)