Skip to content

A lightweight Android PDF viewer library powered by Mozilla's PDF.js, offering seamless PDF rendering and interactive features. Supports both Jetpack Compose and Xml.

License

Notifications You must be signed in to change notification settings

Bhuvaneshw/PdfViewer

Repository files navigation

PdfViewer (Early stage)

A lightweight Android PDF viewer library powered by Mozilla's PDF.js, offering seamless PDF rendering and interactive features.

Screenshots

ScreenShot1 ScreenShot2 ScreenShot3 ScreenShot4 ScreenShot5

Demo

You can download apk from here

Contents

  1. Setup
    1.1. Setup - Kotlin DSL
    1.2. Setup - Groovy DSL
  2. Usage
    2.1. Core PdfViewer
    2.2. Full UI
    2.3. Without PdfViewerContainer
    2.4. Listener
    2.5. Adding extra menu to PdfToolBar
  3. See also
  4. Public Members
  5. License

1. Setup

1.1. Kotlin DSL

Step 1. Add the JitPack repository to your build file

Add it in your root build.gradle.kts or settings.gradle.kts at the end of repositories:

dependencyResolutionManagement {
  repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
  repositories {
    mavenCentral()
    maven("https://jitpack.io")
  }
}

Step 2. Add the dependency

dependencies {
    implementation("com.github.bhuvaneshw.pdfviewer:$module:$version")
}

Replace $module with core, ui, compose and compose-ui Replace $version with latest version
Latest Version:

Example:

Only core PdfViewer

implementation("com.github.bhuvaneshw.pdfviewer:core:1.0.0")

With UI

implementation("com.github.bhuvaneshw.pdfviewer:core:1.0.0")
implementation("com.github.bhuvaneshw.pdfviewer:ui:1.0.0")

Only core Compose PdfViewer

implementation("com.github.bhuvaneshw.pdfviewer:compose:1.0.0")

With Compose UI

implementation("com.github.bhuvaneshw.pdfviewer:compose:1.0.0")
implementation("com.github.bhuvaneshw.pdfviewer:compose-ui:1.0.0")

1.2. Groovy DSL

Step 1. Add the JitPack repository to your build file

Add it in your root build.gradle or settings.gradle at the end of repositories:

dependencyResolutionManagement {
  repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
  repositories {
      mavenCentral()
      maven { url 'https://jitpack.io' }
  }
}

Step 2. Add the dependency

dependencies {
    implementation 'com.github.bhuvaneshw.pdfviewer:$module:$version'
}

2. Usage

2.1 Core PdfViewer

Include PdfViewer in your xml

<com.acutecoder.pdf.PdfViewer
    android:id="@+id/pdf_viewer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/md_theme_primaryContainer"
    app:containerBackgroundColor="@android:color/transparent" />

Then call load function

  // Kotlin
  pdfViewer.onReady {
    load(source)
  }

  // Java
  PdfUtil.onReady(pdfViewer, () -> {
    pdfViewer.load(source);
  });

source can be

  1. Asset Path like "file:///android_asset/sample.pdf"
  2. Android Uri
  3. Network url like "https://example.com/sample.pdf"
  4. Direct file path like "/sdcard/Downloads/sample.pdf" or "file:///sdcard/Downloads/sample.pdf"(not recommended)

Warning

You should not call below members before the PdfViewer is initialized!

  1. PdfViewer.load()
  2. PdfViewer.ui or getUi()
  3. PdfViewer.findController or getFindController()
  4. PdfViewer.pageScrollMode or getPageScrollMode()
  5. PdfViewer.pageSpreadMode or getPageSpreadMode()
  6. PdfViewer.cursorToolMode or getCursorToolMode()

With Compose

Include compose dependency

val pdfState = rememberPdfState(source = source)
PdfViewer(  
    pdfState = pdfState,  
    modifier = Modifier,  
    containerColor = Color.Transparent,  
    onReady = {
      // Optional work
  }  
)

2.2 Full UI

Include core and ui dependencies

<com.acutecoder.pdf.ui.PdfViewerContainer xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/container"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity">

<!-- id is mandatory, if not random int will be assigned by PdfViewerContainer-->
  <com.acutecoder.pdf.ui.PdfToolBar
      android:id="@+id/toolbar"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:contentColor="@color/md_theme_onBackground" />

  <com.acutecoder.pdf.PdfViewer
      android:id="@+id/pdf_viewer"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="@color/md_theme_primaryContainer"
      app:containerBackgroundColor="@android:color/transparent" />

  <com.acutecoder.pdf.ui.PdfScrollBar
      android:id="@+id/pdf_scroll_bar"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:contentColor="@color/md_theme_onBackground"
      app:handleColor="@color/md_theme_background" />

  <LinearLayout
      android:id="@+id/loading_indicator"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_below="@id/toolbar"
      android:background="@color/md_theme_background"
      android:gravity="center"
      android:visibility="gone">

      <ProgressBar
          android:layout_width="wrap_content"
          android:layout_height="wrap_content" />

  </LinearLayout>

</com.acutecoder.pdf.ui.PdfViewerContainer>

Then load the file

pdfViewer.onReady {
    load(source)
    toolbar.setFileName(fileName) // or toolbar.setTitle(title)
}
container.setAsLoadingIndicator(loadingIndicator)

With Compose

Include compose and compose-ui dependencies

val pdfState = rememberPdfState(source = source)  

PdfViewerContainer(  
   pdfState = pdfState,  
   pdfViewer = {  
      PdfViewer(  
         modifier = Modifier.fillMaxSize(),  
         containerColor = Color.Transparent, 
      )  
   },  
   pdfToolBar = {  
      PdfToolBar(  
         title = title,  
         onBack = { finish() },  
         contentColor = MaterialTheme.colorScheme.onBackground
      )  
   },  
   pdfScrollBar = { parentHeight ->  
      PdfScrollBar(  
         parentHeight = parentHeight,  
         contentColor = MaterialTheme.colorScheme.onBackground,  
         handleColor = MaterialTheme.colorScheme.background  
      )  
   },  
   loadingIndicator = {  
      Column(  
         modifier = Modifier  
            .fillMaxSize()  
            .background(MaterialTheme.colorScheme.background),  
         verticalArrangement = Arrangement.Center,  
         horizontalAlignment = Alignment.CenterHorizontally,  
      ) { 
         CircularProgressIndicator()  
         Text(text = "Loading...")  
      }  
 })

2.3 Without PdfViewerContainer

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.acutecoder.pdf.ui.PdfToolBar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:contentColor="@color/md_theme_onBackground" />

<!--    add below toolbar-->
    <com.acutecoder.pdf.PdfViewer
        android:id="@+id/pdf_viewer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/toolbar"
        android:background="@color/md_theme_primaryContainer"
        app:containerBackgroundColor="@android:color/transparent" />

<!--    set align parent right, don't add below toolbar-->
    <com.acutecoder.pdf.ui.PdfScrollBar
        android:id="@+id/pdf_scroll_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        app:contentColor="@color/md_theme_onBackground"
        app:handleColor="@color/md_theme_background" />

</RelativeLayout>

And then

pdfToolBar.setupWith(pdfViewer)
pdfScrollBar.setupWith(pdfViewer, pdfToolBar)
pdfViewer.onReady {
  load(source)
  toolbar.setFileName(fileName) // or toolbar.setTitle(title)
}

2.4 Listener

You can add listener like

pdfViewer.addListener(PdfOnPageLoadFailed {  // Specific listener (Extension functions)
})

or

pdfViewer.addListener(object: PdfListener {
  // implement required methods
})

Note

For Download listener see implementation in PdfViewerActivity.kt

2.5 Adding extra menu to PdfToolBar

See ExtendedToolBar.kt

3. See also

4. Public Members

isInitialized: Boolean Indicates whether the PDF viewer has been initialized.

currentUrl: String? The current URL of the loaded PDF document.

currentPage: Int The current page number of the PDF document.

pagesCount: Int The total number of pages in the currently loaded PDF document.

currentPageScale: Float The scale factor of the current page (zoom level).

currentPageScaleValue: String The current scale value of the PDF page (e.g., page-fit, auto).

properties: PdfDocumentProperties? The properties of the currently loaded PDF document, such as title, author, etc.

ui: UiSettings Returns the UiSettings for the PDF viewer. Provides settings related to the UI provided by Mozill's PDF.js.

findController: FindController Returns the FindController for the PDF viewer. Provides functionality for finding text in the PDF.

pageScrollMode: PageScrollMode Defines the page scroll mode (e.g., vertical, horizontal, wrapped).

pageSpreadMode: PageSpreadMode Defines the page spread mode (e.g., none, odd, even).

cursorToolMode: CursorToolMode Defines the cursor tool mode (e.g., text select, hand tool).

load(url: String, originalUrl: String = url) Loads a PDF file from the specified url. The originalUrl parameter is optional and defaults to the url.

onReady(onReady: PdfOnReadyListener) Registers a listener that gets called when the PDF viewer is initialized and ready.

addListener(listener: PdfListener) Adds a listener to be notified of PDF events (e.g., page load).

removeListener(listener: PdfListener) and removeListener(listener: PdfOnReadyListener) Removes a previously added listener.

goToPage(pageNumber: Int) Navigates to the specified page number in the PDF.

scrollToRatio(ratio: Float) Scrolls the viewer to a specific ratio (0f - 1f) (calculated to offset).

scrollTo(offset: Int) Scrolls the viewer to the specified offset.

goToNextPage() Navigates to the next page in the PDF.

goToPreviousPage() Navigates to the previous page in the PDF.

goToFirstPage() Navigates to the first page in the PDF.

goToLastPage() Navigates to the last page in the PDF.

scalePageTo(scale: Float) Zooms the current page to the specified scale factor.

zoomIn() Zooms in on the current page.

zoomOut() Zooms out on the current page.

zoomTo(zoom: Zoom) Zooms to a specified zoom mode (e.g., PAGE_FIT, PAGE_WIDTH).

downloadFile() Initiates the download of the currently viewed PDF file.

printFile() - unstable Prints the currently viewed PDF file.

startPresentationMode() - unstable Starts presentation mode, which is typically used for viewing PDFs in full-screen mode.

rotateClockWise() Rotates the PDF clockwise by 90 degrees.

rotateCounterClockWise() Rotates the PDF counter-clockwise by 90 degrees.

showDocumentProperties() Displays the properties of the current PDF document (e.g., title, author).

reInitialize() Re-initializes the PDF viewer, reloading the webview.

setContainerBackgroundColor(color: Int) Sets the background color of the PDF viewer container.

5. License

PDF.js License

Copyright 2025 Bhuvaneshwaran

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

About

A lightweight Android PDF viewer library powered by Mozilla's PDF.js, offering seamless PDF rendering and interactive features. Supports both Jetpack Compose and Xml.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published