I have a Xamarin Forms app where I want to open a locally stored PDF. I don\'t need to load them within the app, I\'m fine with shelling out to the device\'s default documen
I had to do something and solve it using a DependencyService . You can use it to open the pdf depending on each platform
I show you an example of how to solve it on Android :
IPdfCreator.cs:
public interface IPdfCreator
{
void ShowPdfFile();
}
MainPage.cs:
private void Button_OnClicked(object sender, EventArgs e)
{
DependencyService.Get<IPdfCreator>().ShowPdfFile();
}
PdfCreatorAndroid.cs
[assembly: Dependency(typeof(PdfCreatorAndroid))]
namespace Example.Droid.DependecyServices
{
public class PdfCreatorAndroid : IPdfCreator
{
public void ShowPdfFile()
{
var fileLocation = "/sdcard/Template.pdf";
var file = new File(fileLocation);
if (!file.Exists())
return;
var intent = DisplayPdf(file);
Forms.Context.StartActivity(intent);
}
public Intent DisplayPdf(File file)
{
var intent = new Intent(Intent.ActionView);
var filepath = Uri.FromFile(file);
intent.SetDataAndType(filepath, "application/pdf");
intent.SetFlags(ActivityFlags.ClearTop);
return intent;
}
}
}
Result: http://i.stack.imgur.com/vrwzt.png
Here there is a good project that uses MuPDF Library in xamarin . I've tested it and it works properly.
With MuPDF you can zoom out , zoom in and even write some note on PDFs.
I've recently done this in my own project using a custom renderer. First implement an empty Xamarin forms view such as (I've included a bindable FilePath attribute):
public class PdfViewer : View
{
public static readonly BindableProperty FilePathProperty =
BindableProperty.Create<DocumentViewer, string>(p => p.FilePath, null);
public string FilePath
{
get
{
return (string)this.GetValue(FilePathProperty);
}
set
{
this.SetValue(FilePathProperty, value);
}
}
}
Then create an iOS Renderer that will be registered for this control. This renderer can, as it is within an iOS project, use the Quick Look Preview Controller to delegate to the built in iOS pdf viewer:
[assembly: ExportRenderer(typeof(PdfViewer), typeof(DocumentViewRenderer))]
public class DocumentViewRenderer
: ViewRenderer<PdfViewer, UIView>
{
private QLPreviewController controller;
protected override void OnElementChanged(ElementChangedEventArgs<DocumentViewer> e)
{
base.OnElementChanged(e);
this.controller = new QLPreviewController();
this.controller.DataSource = new DocumentQLPreviewControllerDataSource(e.NewElement.FilePath);
SetNativeControl(this.controller.View);
}
private class DocumentQLPreviewControllerDataSource : QLPreviewControllerDataSource
{
private string fileName;
public DocumentQLPreviewControllerDataSource(string fileName)
{
this.fileName = fileName;
}
public override int PreviewItemCount(QLPreviewController controller)
{
return 1;
}
public override QLPreviewItem GetPreviewItem(QLPreviewController controller, int index)
{
var documents = NSBundle.MainBundle.BundlePath;
var library = Path.Combine(documents, this.fileName);
NSUrl url = NSUrl.FromFilename(library);
return new QlItem(string.Empty, url);
}
private class QlItem : QLPreviewItem
{
public QlItem(string title, NSUrl uri)
{
this.ItemTitle = title;
this.ItemUrl = uri;
}
public override string ItemTitle { get; private set; }
public override NSUrl ItemUrl { get; private set; }
}
}
}
I haven't compiled and run this as I've extracted it from my larger project but in general this should work.