Simple UIScrollView / CATiledLayer PDF Example (MonoTouch version)

Monday, 28 February 2011 04:52 by Krumelur

Searching the web for a simple example how to preview a PDF page using a CATiledLayer, I found some code on Olive Toast's blog: http://www.olivetoast.com/blog/2009/08/simple-uiscrollview-catiledlayer-pdf-example/

A very small and lean solution to demonstrate viewing, zooming and scrolling a page of a PDF. The code can easily be extended to a full PDF viewer which uses only very little memory.

I went and MonoTouched the example. You can download the sample's main file here PdfDemo.cs.zip (1,59 kb) . Also check out the source below:

 

using System;
using MonoTouch.Foundation;
using System.IO;
using MonoTouch.UIKit;
using System.Text;
using System.Diagnostics;
using System.Drawing;
using MonoTouch.CoreGraphics;
using MonoTouch.CoreAnimation;

namespace iOSTest
{
    public class Application
    {
        static void Main ( string[] args )
        {
            UIApplication.Main ( args );
        }
    }

    // The name AppDelegate is referenced in the MainWindow.xib file.
    public partial class AppDelegate : UIApplicationDelegate
    {
        // This method is invoked when the application has loaded its UI and its ready to run
        public override bool FinishedLaunching ( UIApplication app, NSDictionary options )
        {
            NSUrl u = NSUrl.FromString("http://www.tfl.gov.uk/assets/downloads/standard-tube-map.pdf");
            this.o = new AppDelegate.PdfViewController(u);
            this.o.View.Frame = new RectangleF(0, 20, 320, 480 - 20);
            window.AddSubview(this.o.View);
           
            window.MakeKeyAndVisible();       
            return true;
        }
       
        private PdfViewController o;
       
        /// <summary>
        /// Previews first page of a PDF.
        /// </summary>
        public class PdfViewController : UIViewController
        {
            public PdfViewController(NSUrl oUrl) : base()
            {
                this.oUrl = oUrl;
            }
           
            private NSUrl oUrl;
            private UIView oContentView;
            private CGPDFDocument oPdfDoc;
            private CGPDFPage oPdfPage;
           
            public override void ViewDidLoad ()
            {
                base.ViewDidLoad ();
                Console.WriteLine("Loading PDF: {0}", this.oUrl.ToString());
                this.oPdfDoc = CGPDFDocument.FromUrl(this.oUrl.ToString());
               
                // For demo purposes, show first page only.
                this.oPdfPage = this.oPdfDoc.GetPage(1);
               
                RectangleF oPdfPageRect = this.oPdfPage.GetBoxRect(CGPDFBox.Crop);
               
                // Setup tiled layer.
                CATiledLayer oTiledLayer = new CATiledLayer();
                oTiledLayer.Delegate = new TiledLayerDelegate(this);
                oTiledLayer.TileSize = new SizeF(1024f, 1024f);
                oTiledLayer.LevelsOfDetail = 5;
                oTiledLayer.LevelsOfDetailBias = 5;
                oTiledLayer.Frame = oPdfPageRect;
               
                this.oContentView = new UIView(oPdfPageRect);
                this.oContentView.Layer.AddSublayer(oTiledLayer);
               
                this.View = new UIView();
                this.View.AutoresizingMask =
                    UIViewAutoresizing.FlexibleWidth
                    | UIViewAutoresizing.FlexibleHeight
                    | UIViewAutoresizing.FlexibleTopMargin
                    | UIViewAutoresizing.FlexibleBottomMargin
                    | UIViewAutoresizing.FlexibleLeftMargin
                    | UIViewAutoresizing.FlexibleRightMargin;
                this.View.AutosizesSubviews = true;
               
#if DEBUG
                this.View.Layer.BorderColor = UIColor.Red.CGColor;
                this.View.Layer.BorderWidth = 2f;
#endif
               
                // Prepare scroll view.
                UIScrollView oScrollView = new UIScrollView(this.View.Frame);
                oScrollView.AutoresizingMask = this.View.AutoresizingMask;
                oScrollView.Delegate = new ScrollViewDelegate(this);
                oScrollView.ContentSize = oPdfPageRect.Size;
                oScrollView.MaximumZoomScale = 1000f;
                oScrollView.MinimumZoomScale = 0.1f;
                oScrollView.AddSubview(this.oContentView);
               
                this.View.AddSubview(oScrollView);
            }
           
            public override void ViewDidUnload ()
            {
                base.ViewDidUnload ();
                this.oPdfPage.Dispose();
                this.oPdfDoc.Dispose();
                this.oContentView.Dispose();
                this.oPdfPage = null;
                this.oPdfDoc = null;
                this.oContentView = null;
            }
           
            public class TiledLayerDelegate : CALayerDelegate
            {
                public TiledLayerDelegate(PdfViewController oParentController) : base()
                {
                    this.oParentController = oParentController;
                }
               
                private PdfViewController oParentController;
               
                public override void DrawLayer (CALayer layer, CGContext context)
                {
                    context.SaveState();
                    context.SetRGBFillColor( 1.0f, 1.0f, 1.0f, 1.0f);
                    context.FillRect( context.GetClipBoundingBox());
                    context.TranslateCTM( 0.0f, layer.Bounds.Size.Height);
                    context.ScaleCTM( 1.0f, -1.0f);
                    context.ConcatCTM( this.oParentController.oPdfPage.GetDrawingTransform(CGPDFBox.Crop, layer.Bounds, 0, true));
                    context.DrawPDFPage(this.oParentController.oPdfPage);
                    context.RestoreState();
                }
            }
           
            public class ScrollViewDelegate : UIScrollViewDelegate
            {
                public ScrollViewDelegate(PdfViewController oParentController) : base()
                {
                    this.oParentController = oParentController;
                }
               
                private PdfViewController oParentController;
               
                public override UIView ViewForZoomingInScrollView (UIScrollView scrollView)
                {
                    return this.oParentController.oContentView;
                }
            }
        }
       
    }
}