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 document viewer for PDFs. How can I do this?
I tried sending a WebView to the PDF, but that didn't work, I just got a blank page.
The WebView displays the HTML content inside your app and shows how much content is loading in your HTML and web content of your app. This function is available in Xamarin. Forms.
Xamarin. Essentials provides a single cross-platform API that works with any iOS, Android, or UWP application that can be accessed from shared code no matter how the user interface is created. See the platform & feature support guide for more information on supported operating systems.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With