PdfViewer.Android 2.3.7

dotnet add package PdfViewer.Android --version 2.3.7
                    
NuGet\Install-Package PdfViewer.Android -Version 2.3.7
                    
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="PdfViewer.Android" Version="2.3.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PdfViewer.Android" Version="2.3.7" />
                    
Directory.Packages.props
<PackageReference Include="PdfViewer.Android" />
                    
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 PdfViewer.Android --version 2.3.7
                    
#r "nuget: PdfViewer.Android, 2.3.7"
                    
#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 PdfViewer.Android@2.3.7
                    
#: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=PdfViewer.Android&version=2.3.7
                    
Install as a Cake Addin
#tool nuget:?package=PdfViewer.Android&version=2.3.7
                    
Install as a Cake Tool

PdfViewer.Android - .NET for Android Binding

A .NET for Android (formerly Xamarin.Android) binding library for afreakyelf/Pdf-Viewer - a lightweight (~328KB) PDF viewer using Android's native PdfRenderer.

Features

  • 📄 Load PDFs from URL, file path, assets, or content URI
  • 🔍 Pinch-to-zoom with smooth rendering
  • 📱 Full-screen activity or embeddable view
  • 📊 Progress, page change, and zoom callbacks
  • 🎨 Customizable themes and toolbar styles
  • 💾 Download PDFs to storage
  • 🔄 Page navigation with smooth scrolling

Installation

<PackageReference Include="PdfViewer.Android" Version="2.3.7" />

Quick Start

Option 1: Launch Full-Screen Viewer

using PdfViewer.Wrappers;
using PdfViewer.Util;

// From URL
PdfViewerManager.LaunchFromUrl(
    context: this,
    url: "https://example.com/document.pdf",
    title: "My Document",
    saveToDownloads: false,
    enableDownload: true,
    enableZoom: true);

// From local file path
PdfViewerManager.LaunchFromPath(
    context: this,
    filePath: "/path/to/document.pdf",
    title: "Local PDF",
    saveToDownloads: false,
    fromAssets: false,
    enableZoom: true);

// From Assets folder
PdfViewerManager.LaunchFromPath(
    context: this,
    filePath: "sample.pdf",
    title: "Sample PDF",
    fromAssets: true);

Option 2: Embed PdfRendererView in Layout

AXML Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.rajat.pdfviewer.PdfRendererView
        android:id="@+id/pdfView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

C# Activity Code:

using Android.Content;
using AndroidX.AppCompat.App;
using AndroidX.Lifecycle;
using PdfViewer.Wrappers;
using PdfViewer.Util;
using PdfViewer;

[Activity(Label = "PDF Viewer", MainLauncher = true, Theme = "@style/Theme.AppCompat.Light.NoActionBar")]
public class MainActivity : AppCompatActivity
{
    private PdfRendererView? _pdfView;

    protected override void OnCreate(Bundle? savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.activity_main);

        _pdfView = FindViewById<PdfRendererView>(Resource.Id.pdfView);
        if (_pdfView == null) return;

        // Enable zoom
        _pdfView.ZoomEnabled = true;

        // Set up status listener
        var statusListener = new PdfStatusListener();
        statusListener.PageChanged += (s, e) => 
            Console.WriteLine($"Page {e.CurrentPage + 1}/{e.TotalPages}");
        statusListener.Error += (s, e) => 
            Console.WriteLine($"Error: {e.Message}");
        _pdfView.StatusListener = statusListener;

        // Load PDF from URL
        LoadPdfFromUrl("https://www.princexml.com/samples/icelandic/dictionary.pdf");
    }

    private void LoadPdfFromUrl(string url)
    {
        if (_pdfView == null) return;

        // Get lifecycle scope for coroutine support
        var scope = LifecycleOwnerKt.GetLifecycleScope(this);
        
        _pdfView.InitWithUrl(
            url,
            new HeaderData(),
            scope,
            this.Lifecycle,
            CacheStrategy.MaximizePerformance!);
    }
}

Complete Example with All Features

using Android.Content;
using AndroidX.AppCompat.App;
using AndroidX.Lifecycle;
using PdfViewer.Wrappers;
using PdfViewer.Util;
using PdfViewer;

public class MainActivity : AppCompatActivity
{
    private PdfRendererView? _pdfView;
    private ProgressBar? _progressBar;
    private int _currentPage;
    private int _totalPages;
    private const int FilePickerRequestCode = 100;

    protected override void OnCreate(Bundle? savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.activity_main);

        _pdfView = FindViewById<PdfRendererView>(Resource.Id.pdfView);
        _progressBar = FindViewById<ProgressBar>(Resource.Id.progressBar);

        if (_pdfView == null) return;

        // Enable zoom
        _pdfView.ZoomEnabled = true;

        // Set up comprehensive status listener
        var statusListener = new PdfStatusListener();
        
        statusListener.PdfLoadStarted += (s, e) =>
        {
            RunOnUiThread(() =>
            {
                _progressBar!.Progress = 0;
                _progressBar.Visibility = Android.Views.ViewStates.Visible;
            });
        };
        
        statusListener.PdfLoadProgress += (s, e) =>
        {
            RunOnUiThread(() =>
            {
                _progressBar!.Progress = e.Progress;
                var totalMB = e.TotalBytes.HasValue 
                    ? $"/{e.TotalBytes.Value / 1024.0 / 1024.0:F2}MB" 
                    : "";
                Console.WriteLine($"Downloading: {e.Progress}% ({e.DownloadedBytes / 1024.0 / 1024.0:F2}MB{totalMB})");
            });
        };
        
        statusListener.PdfLoadSuccess += (s, path) =>
        {
            RunOnUiThread(() =>
            {
                _progressBar!.Visibility = Android.Views.ViewStates.Gone;
                Console.WriteLine($"PDF loaded: {System.IO.Path.GetFileName(path)}");
            });
        };
        
        statusListener.PdfRenderSuccess += (s, e) =>
        {
            RunOnUiThread(() =>
            {
                _progressBar!.Visibility = Android.Views.ViewStates.Gone;
                Console.WriteLine("PDF rendered successfully");
            });
        };
        
        statusListener.PageChanged += (s, e) =>
        {
            _currentPage = e.CurrentPage;
            _totalPages = e.TotalPages;
            RunOnUiThread(() =>
            {
                Console.WriteLine($"Page {e.CurrentPage + 1}/{e.TotalPages}");
            });
        };
        
        statusListener.Error += (s, e) =>
        {
            RunOnUiThread(() =>
            {
                _progressBar!.Visibility = Android.Views.ViewStates.Gone;
                Console.WriteLine($"Error: {e.Message}");
            });
        };
        
        _pdfView.StatusListener = statusListener;

        // Set up zoom listener
        var zoomListener = new PdfZoomListener();
        zoomListener.ZoomChanged += (s, e) =>
        {
            RunOnUiThread(() =>
            {
                var zoomState = e.IsZoomedIn ? "Zoomed In" : "Normal";
                Console.WriteLine($"Zoom: {e.Scale:P0} ({zoomState})");
            });
        };
        _pdfView.ZoomListener = zoomListener;

        // Load default PDF
        LoadPdfFromUrl("https://www.princexml.com/samples/icelandic/dictionary.pdf");
    }

    private void LoadPdfFromUrl(string url)
    {
        if (_pdfView == null) return;

        // Close any existing PDF before loading a new one
        _pdfView.ClosePdfRender();

        var scope = LifecycleOwnerKt.GetLifecycleScope(this);
        
        _pdfView.InitWithUrl(
            url,
            new HeaderData(),
            scope,
            this.Lifecycle,
            CacheStrategy.MaximizePerformance!);
    }

    // Page navigation
    private void GoToPreviousPage()
    {
        if (_currentPage > 0)
            _pdfView?.JumpToPage(_currentPage - 1, smoothScroll: true, delayMillis: 300);
    }

    private void GoToNextPage()
    {
        if (_currentPage < _totalPages - 1)
            _pdfView?.JumpToPage(_currentPage + 1, smoothScroll: true, delayMillis: 300);
    }

    // Load from file picker
    private void OpenFilePicker()
    {
        var intent = new Intent(Intent.ActionGetContent);
        intent.SetType("application/pdf");
        StartActivityForResult(intent, FilePickerRequestCode);
    }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent? data)
    {
        base.OnActivityResult(requestCode, resultCode, data);

        if (requestCode == FilePickerRequestCode && resultCode == Result.Ok && data?.Data != null)
        {
            var uri = data.Data;
            var filePath = CopyUriToTempFile(uri);
            if (filePath != null)
            {
                _pdfView?.ClosePdfRender();
                _pdfView?.InitWithFile(
                    new Java.IO.File(filePath),
                    CacheStrategy.MaximizePerformance!);
            }
        }
    }

    private string? CopyUriToTempFile(Android.Net.Uri uri)
    {
        try
        {
            var inputStream = ContentResolver?.OpenInputStream(uri);
            if (inputStream == null) return null;

            var tempFile = Java.IO.File.CreateTempFile("temp_pdf", ".pdf", CacheDir);
            var outputStream = new Java.IO.FileOutputStream(tempFile);
            
            var buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = inputStream.Read(buffer)) > 0)
            {
                outputStream.Write(buffer, 0, bytesRead);
            }
            
            inputStream.Close();
            outputStream.Close();

            return tempFile.AbsolutePath;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error copying file: {ex.Message}");
            return null;
        }
    }
}

API Reference

PdfRendererView Properties

Property Type Description
StatusListener PdfRendererView.IStatusCallBack Set callbacks for load/render events
ZoomListener PdfRendererView.IZoomListener Set callbacks for zoom events
ZoomEnabled bool Enable/disable pinch-to-zoom

PdfRendererView Methods

Method Description
InitWithUrl(url, headers, scope, lifecycle, cacheStrategy) Load PDF from URL
InitWithFile(file, cacheStrategy) Load PDF from local file
JumpToPage(pageNumber, smoothScroll, delayMillis) Navigate to specific page
ClosePdfRender() Close current PDF and release resources

PdfStatusListener Events

Event Arguments Description
PdfLoadStarted EventArgs PDF loading started
PdfLoadProgress PdfLoadProgressEventArgs Download progress update
PdfLoadSuccess string (file path) PDF loaded successfully
PdfRenderStarted EventArgs PDF rendering started
PdfRenderSuccess EventArgs PDF rendered successfully
PageChanged PageChangedEventArgs Current page changed
Error Throwable Error occurred

PdfZoomListener Events

Event Arguments Description
ZoomChanged ZoomChangedEventArgs Zoom level changed

Event Arguments

// PdfLoadProgressEventArgs
public record PdfLoadProgressEventArgs(
    int Progress,           // 0-100 percentage
    long DownloadedBytes,   // Bytes downloaded
    long? TotalBytes);      // Total size (null if unknown)

// PageChangedEventArgs  
public record PageChangedEventArgs(
    int CurrentPage,        // 0-based page index
    int TotalPages);        // Total page count

// ZoomChangedEventArgs
public record ZoomChangedEventArgs(
    bool IsZoomedIn,        // True if zoomed beyond 1.0
    float Scale);           // Current zoom scale

Requirements

  • .NET 10.0 Android or later
  • Minimum SDK: 21 (Android 5.0)
  • Target SDK: 36 (Android 16)

Dependencies

The binding automatically includes required dependencies:

  • Xamarin.Kotlin.StdLib
  • Xamarin.AndroidX.Core
  • Xamarin.AndroidX.AppCompat
  • Xamarin.AndroidX.RecyclerView
  • Xamarin.AndroidX.Lifecycle.Runtime.Ktx
  • Xamarin.KotlinX.Coroutines.Android
  • Square.OkHttp3

Permissions

Add to your AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

License

Original library: MIT License by afreakyelf
.NET Binding: MIT License

Credits

Product Compatible and additional computed target framework versions.
.NET net10.0-android36.0 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
2.3.7 490 12/10/2025