Xamarin.iOS: Draw PDF to a custom UIView

None
9/7/2016

Downloads

In this code sample , we will create a Xamarin.iOS application and add a custom UIView that overrides method Draw to display a PDF page. To keep the code sample simple, the PDF document itself is embedded as a resource. In a more realistic code sample it would be selected from the device or cloud storage.

We will show the relevant code snippets. You can download the full code sample above.

iphone

We edit AppDelegate.cs so that FinishedLaunching executes the following tasks:

  • create a PDF Page object from "tiger.pdf" that is embedded as a resource
  • create a new controller and set its View property to a new PdfPageView
  • show it

It looks as follows:

public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
   // create a PDF Page object from "tiger.pdf" that is embedded as a resource
   Assembly assembly = Assembly.GetExecutingAssembly();
   MemoryStream stream = new MemoryStream();
   using (Stream resourceStream = assembly.GetManifestResourceStream("DrawPdf.iOS.tiger.pdf"))
   {
      resourceStream.CopyTo(stream);
   }
   Page page = new Page(stream, 0);

   // create a new controller and set its View to a new PdfPageView 
   var controller = new UIViewController();
   controller.View = new PdfPageView(page);
   controller.View.BackgroundColor = UIColor.LightGray;

   // show it
   Window = new UIWindow(UIScreen.MainScreen.Bounds);
   Window.RootViewController = controller;
   Window.MakeKeyAndVisible();

   return true;
}

PdfPageView

The custom View PdfPageView is actually quite simple. It overrides method Draw to draw the PDF Page that was passed to its constructor to a CGContext instance that is retrieved by calling GetCutrrentContext(). In addition it transforms CGContext to show the PDF as expected.

Here is the Draw implementation (download the full code sample above):

public override void Draw(CGRect rect)
{
   base.Draw(rect);

   using (CGContext context = UIGraphics.GetCurrentContext())
   {
      // scale to fit the page
      float scaleX = (float)(rect.Width / _page.Width);
      float scaleY = (float)(rect.Height / _page.Height);
      float scale = Math.Min(scaleX, scaleY);
      context.ScaleCTM(scale, scale);
     
      // flip verically - the y-axis of PDF points up instead of down
      context.ScaleCTM(1, -1);
      context.TranslateCTM(0, (float)-_page.Height);

       _page.Draw(context);
   }
}