TheBetterPdfViewer.MAUI 1.7.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package TheBetterPdfViewer.MAUI --version 1.7.0
                    
NuGet\Install-Package TheBetterPdfViewer.MAUI -Version 1.7.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TheBetterPdfViewer.MAUI" Version="1.7.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TheBetterPdfViewer.MAUI" Version="1.7.0" />
                    
Directory.Packages.props
<PackageReference Include="TheBetterPdfViewer.MAUI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TheBetterPdfViewer.MAUI --version 1.7.0
                    
#r "nuget: TheBetterPdfViewer.MAUI, 1.7.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TheBetterPdfViewer.MAUI@1.7.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TheBetterPdfViewer.MAUI&version=1.7.0
                    
Install as a Cake Addin
#tool nuget:?package=TheBetterPdfViewer.MAUI&version=1.7.0
                    
Install as a Cake Tool

TheBetterPdfViewer.MAUI

A .NET MAUI PDF viewer control with native rendering and embedded-video playback.

Features

  • Annotations (highlight, ink, sticky notes, free text, signatures)
  • User bookmarks + document outline navigation
  • Form fields (text, checkbox, radio, signature) with XFDF export
  • Save an annotated copy — SaveDocumentAsync(path) flattens annotations, signatures and form-field ink into the pages. The result matches what the viewer displayed, and matches across devices: a file saved on Android and one saved on an iPad look the same. Form values, links, embedded video and the outline are preserved. Use ExportAnnotationsAsync instead if you need the marks to stay editable.
  • Text search and selection
  • Embedded video detection + playback — surfaces /Movie, /Screen, /RichMedia, and /FileAttachment annotations as well as document-level /Names /EmbeddedFiles entries. Set EnableInPageVideoOverlay="True" to mount tap-to-play ▶ buttons over each video's annotation rect on visible pages.
  • Tap-to-show toolbar — the floating toolbar starts hidden and appears when the user taps the page, fading out again after five seconds. Set AutoShowToolbar="True" for the earlier behaviour: shown when the document opens and again whenever the page changes.
  • Zoom controls — zoom in / out / reset buttons in the built-in toolbar on all platforms, alongside pinch-to-zoom. Bounds are configurable via MinZoomFactor and MaxZoomFactor; ResetZoom() returns to fit-page (SinglePage) or fit-width (Continuous). On iOS, MacCatalyst, and Android, the toolbar scrolls horizontally on narrow screens so every control stays reachable.

Platforms

  • iOS 15+ (PDFKit + CoreGraphics CGPDFDocument; PDFium for saving)
  • MacCatalyst 15+ (PDFKit + CoreGraphics CGPDFDocument; PDFium for saving)
  • Android 33+ (PDFium)
  • Windows (PDFium)

Annotations are drawn by one shared SkiaSharp painter on every platform, so they render identically wherever they are shown or saved.

Embedded video usage

// MauiProgram.cs - this also registers CommunityToolkit.Maui.MediaElement.
builder.UseTheBetterPdfViewer();
// XAML / code-behind
viewer.EmbeddedVideosChanged += (s, e) =>
{
    foreach (var video in e.Videos)
        Console.WriteLine($"p.{video.PageNumber} {video.AnnotationKind} {video.FileName}");
};

// Option 1: open a video at the user's request via the modal player.
await viewer.PlayEmbeddedVideoAsync(viewer.EmbeddedVideos[0]);

// Option 2: let the viewer overlay tappable ▶ buttons over each video
// annotation. Tapping a button opens the same modal player.
viewer.EnableInPageVideoOverlay = true;

License

MIT

1.7.0 notes

New: headless document API (all platforms, PDFium). PdfDocumentTools reads page counts, page sizes and the outline, and ExtractPage writes one page as a new unencrypted PDF. PdfDocumentBuilder builds a PDF by importing pages from other files and composing simple pages: Helvetica text, images (a JPEG is embedded as-is) and invisible link annotations, in top-left-origin point coordinates. Text outside the WinAnsi (Western European) set is drawn as ?. Calls are serialized with the library's other background PDFium work (such as saving), but not with the viewer's own rendering on Android and Windows, so call them from the viewer's (UI) thread.

PdfDocumentTools.ExtractPage(source, pageIndex: 2, "page3.pdf");

using var deck = new PdfDocumentBuilder();
deck.ImportPage("page3.pdf", 0);
var page = deck.AddPage();                       // A4
var (w, _) = page.MeasureText("Intro video", 20);
page.DrawText("Intro video", (page.Width - w) / 2, 40, 20);
page.DrawImage(thumbnail, 60, 80, 475, 267);
page.AddLink(60, 80, 475, 267, "https://example.com/intro");
deck.Save("deck.pdf");

XFDF export is standard, and never empty. ExportAnnotationsAsync and ExportFormDataAsync always write a complete document (<annots/> / <fields/> when there is nothing). Annotations now carry rect and, for highlights, coords (one quad per line) as attributes, with comma-separated ink points — the shape Adobe and other XFDF readers expect; 1.6 wrote <rect> elements and ;-separated points. Signed signature form fields are exported as <ink subject="Signature"> in page coordinates (1.6 exported only "[Signed]" in the form data), and signature annotations land where they were drawn.

Links. PdfHyperlinkClickedEventArgs.RawUri is the link's /URI exactly as stored in the PDF, and Uri is a safe parse that may be relative or null. A relative link such as playvideo/123, or one with spaces, used to throw (crashing Android and Windows) or be dropped (Apple). When no handler sets Handled, iOS and MacCatalyst open only absolute http, https, mailto and tel links; Android and Windows never open links themselves, as in 1.6. This changes behaviour on Apple, which used to open every link: sms:, itms-apps: and custom schemes are no longer opened by default, so handle HyperlinkClicked to open them.

Load failures. PdfDocumentLoadFailedEventArgs.Reason says why a document did not open (PasswordRequired, InvalidPassword, InvalidFormat, FileNotFound, Unknown). Set Password and call the new Reload() to retry. Android no longer raises DocumentLoaded for a document it could not open, and iOS no longer shows a locked document as blank pages.

Page events. PageChanged.IsUserInitiated is now accurate on every platform. A host GoToPage is programmatic, even when called from inside a PageChanged handler, so reverting the user's flip works (on iOS and Mac it used to leave the screen on the other page). The viewer's own controls (toolbar page entry, QuickSwipe, bookmark taps, links to other pages) count as the user. Android no longer reports every frame of a continuous-mode jump, iOS and Mac no longer report a fake user change to page 1 when a document is reloaded, and Windows no longer snaps the page back into place after the user scrolls.

Also: ClearFormData() resets the fields without re-raising DocumentLoaded and keeps the page; ShowAnnotationButton now works on Android, Windows and MacCatalyst (it was iOS only). On Windows, the code that opens a PDF by path now accepts non-ASCII paths: the headless API, PdfToImageConverter and embedded-video attachments. The Windows viewer itself already loaded documents from memory and was not affected. Mac Catalyst: clicking a link works (PDFKit there ignores link clicks); a page link raises HyperlinkClicked with PageNumber, then navigates unless handled. iOS and Mac Catalyst: documents open fitted (page in SinglePage, width in Continuous) and stay fitted as the view resizes, and setting MinZoomFactor/MaxZoomFactor no longer turns fitting off (Mac opened at scale 1; iOS drew its first frame at scale 1).

Breaking changes. new PdfHyperlinkClickedEventArgs(null, 3) no longer compiles: null is ambiguous between the (Uri?, int?) and new (string?, int?) constructors, so cast it ((Uri?)null). ITheBetterPdfViewer gains Reload(), which implementers of the interface must add. ClearFormData() no longer raises DocumentLoaded. The XFDF shape changed (rect/coords attributes, comma-separated ink points; see above). On iOS and MacCatalyst, unhandled links other than http, https, mailto and tel are no longer opened (see Links).

1.6.6 notes

Fixes two iOS crashes.

  • Closing a PDF crashed older iPads (iOS 15-17). 1.6.3 reduced this but did not end it. The viewer listens for scroll changes on PDFKit's internal scroll view, and that listener was never removed on close: .NET's AddObserver only unregisters while the scroll view's .NET wrapper is alive, and nothing kept it alive. When iOS freed the view it notified the dead listener. The handler now holds the scroll view until the listener is removed.
  • Drawing a page tile with no context crashed the app. PDFKit occasionally asks a page to draw with no context; the tile is now skipped instead.

1.6.5 notes

Behaviour change: the toolbar starts hidden. The floating toolbar no longer appears when a document opens or when the page changes; the user taps the page to bring it up, and it still fades after five seconds. Set AutoShowToolbar="True" to keep the old behaviour.

Form-field text is one size everywhere. Text and choice fields used to size their text from the field's height, so a tall multi-line box drew its value several times bigger than a single-line field on the same form. Every field now draws at 12pt in black, shrinking only in a field too short to hold that. On iOS and macCatalyst the text was also drawn in Times, because the system font's name does not survive into the field's appearance; it is Helvetica now, which also reads correctly in a saved copy opened in another viewer.

1.6.2 notes

Fixes iOS App Store validation. 1.6.0 shipped PDFium as a loose dylib, which Apple rejects (error 90171); 1.6.1 wrapped it in a framework whose declared minimum OS did not match its binary, which Apple also rejects (ITMS-90208). 1.6.2 ships a signed pdfium.xcframework retargeted to iOS 15.0 with matching metadata. Do not use 1.6.0 or 1.6.1 for iOS — both fail upload.

Regenerate it with build/make-pdfium-xcframework.sh after a PDFium bump.

1.6.0 notes

Saving. SaveDocumentAsync(Stream) and SaveDocumentAsync(string) write a copy with annotations flattened in; the source file is never modified. The flattened marks are not editable annotations in the saved file — that is the trade that makes the file match the screen.

One exception, iOS and macCatalyst only: a document that has form fields loses its embedded video when saved. Live form values exist inside PDFKit's widgets and nowhere else, so those documents must be serialized by PDFKit, and that serializer drops embedded media. Documents without form fields are read from the original file and keep everything. Android and Windows are never affected.

Cross-device rendering, measured. Annotating the same document on an Android tablet and an iPhone simulator and diffing the two saved PDFs: highlights, ink, notes and signatures come out pixel-identical. Text annotations do not quite — glyph-edge antialiasing differs, 2,165 pixels of a 1600x900 render (0.15%), entirely inside the text's own bounding box and indistinguishable side by side at 4x magnification. It is not hinting or edging settings, and not the glyph rasterizer (drawing glyphs as filled outlines instead changed almost nothing); the likeliest cause is a sub-pixel baseline difference from font metrics. If you need text bit-identical too, that is where to look.

Behaviour change: annotation anchors. Note and text annotations now anchor consistently across platforms — NoteX/NoteY is the top-left corner for both. Annotations persisted by an earlier version will shift the first time 1.6.0 displays them: notes on iOS and macCatalyst, text on Android. This is a one-time correction and nothing needs migrating.

Fixed, Windows only: ink drew at half the requested width, the note icon was fixed at 16 device pixels and never scaled with zoom, and signatures ignored the chosen colour in favour of hardcoded dark blue. Text annotations were XAML overlays above the page image, so they never appeared in exported or bitmap output at all.

Fixed, iOS and macCatalyst: a large ink stroke's bounding box no longer swallows taps on links drawn inside it.

Product Compatible and additional computed target framework versions.
.NET net10.0-android36.0 is compatible.  net10.0-ios26.0 is compatible.  net10.0-maccatalyst26.0 is compatible.  net10.0-windows10.0.19041 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.7.1 47 9/25/2026
1.7.0 45 9/25/2026
1.6.6 48 9/24/2026
1.6.5 99 9/18/2026
1.6.4 89 9/16/2026
1.6.3 103 9/10/2026
1.6.2 122 8/22/2026
1.6.1 98 8/21/2026
1.5.1 106 8/19/2026
1.5.0 96 8/19/2026
1.4.7 139 7/22/2026
1.4.6 121 7/17/2026
1.4.5 114 7/17/2026
1.4.4 113 7/16/2026
1.4.3 110 7/13/2026
1.4.2 117 7/13/2026
1.4.1 126 7/10/2026
1.4.0 152 5/28/2026
1.3.0 128 5/8/2026
Loading failed