Giter Club home page Giter Club logo

react-native-pdf's Introduction

react-native-pdf

npm

A react native PDF view component (cross-platform support)

Feature

  • read a PDF from url, blob, local file or asset and can cache it.
  • display horizontally or vertically
  • drag and zoom
  • double tap for zoom
  • support password protected pdf
  • jump to a specific page in the pdf

Supported versions

We use react-native-blob-util to handle file system access in this package, So you should install react-native-pdf and react-native-blob-util

The table below shows the supported versions of React Native and react-native-blob-util for different versions of react-native-pdf.

React Native 0.4x - 0.56 0.57 0.60+ 0.62+ 0.62+
react-native-pdf 4.x.x - 5.0.x 5.0.9+ 6.0.0+ 6.2.0+ 6.4.0+
react-native-blob-util 0.13.7+

🚨 Expo: This package is not available in the Expo Go app. Learn how you can use this package in Custom Dev Clients via the out-of-tree Expo Config Plugin. Example: with-pdf.

Installation

# Using npm
npm install react-native-pdf react-native-blob-util --save

# or using yarn:
yarn add react-native-pdf react-native-blob-util

Then follow the instructions for your platform to link react-native-pdf into your project:

iOS installation

iOS details

React Native 0.60 and above

Run pod install in the ios directory. Linking is not required in React Native 0.60 and above.

React Native 0.59 and below

react-native link react-native-blob-util
react-native link react-native-pdf

Android installation

Android details

If you use RN 0.59.0 and above, please add following to your android/app/build.gradle**

android {

+    packagingOptions {
+       pickFirst 'lib/x86/libc++_shared.so'
+       pickFirst 'lib/x86_64/libjsc.so'
+       pickFirst 'lib/arm64-v8a/libjsc.so'
+       pickFirst 'lib/arm64-v8a/libc++_shared.so'
+       pickFirst 'lib/x86_64/libc++_shared.so'
+       pickFirst 'lib/armeabi-v7a/libc++_shared.so'
+     }

   }

React Native 0.59.0 and below

react-native link react-native-blob-util
react-native link react-native-pdf

Windows installation

Windows details
  • Open your solution in Visual Studio 2019 (eg. windows\yourapp.sln)
  • Right-click Solution icon in Solution Explorer > Add > Existing Project...
  • If running RNW 0.62: add node_modules\react-native-pdf\windows\RCTPdf\RCTPdf.vcxproj
  • If running RNW 0.62: add node_modules\react-native-blob-util\windows\ReactNativeBlobUtil\ReactNativeBlobUtil.vcxproj
  • Right-click main application project > Add > Reference...
  • Select progress-view and in Solution Projects
    • If running 0.62, also select RCTPdf and ReactNativeBlobUtil
  • In app pch.h add #include "winrt/RCTPdf.h"
    • If running 0.62, also select #include "winrt/ReactNativeBlobUtil.h"
  • In App.cpp add PackageProviders().Append(winrt::progress_view::ReactPackageProvider()); before InitializeComponent();
    • If running RNW 0.62, also add PackageProviders().Append(winrt::RCTPdf::ReactPackageProvider()); and PackageProviders().Append(winrt::ReactNativeBlobUtil::ReactPackageProvider());

Bundling PDFs with the app

To add a test.pdf like in the example add:

<None Include="..\..\test.pdf">
  <DeploymentContent>true</DeploymentContent>
</None>

in the app .vcxproj file, before <None Include="packages.config" />.

FAQ

FAQ details

Q1. After installation and running, I can not see the pdf file.
A1: maybe you forgot to excute react-native link or it does not run correctly. You can add it manually. For detail you can see the issue #24 and #2

Q2. When running, it shows 'Pdf' has no propType for native prop RCTPdf.acessibilityLabel of native type 'String'
A2. Your react-native version is too old, please upgrade it to 0.47.0+ see also #39

Q3. When I run the example app I get a white/gray screen / the loading bar isn't progressing .
A3. Check your uri, if you hit a pdf that is hosted on a http you will need to do the following:

iOS: add an exception for the server hosting the pdf in the ios info.plist. Here is an example :

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow HTTP requests-->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

Android: see here

Q4. why doesn't it work with react native expo?.
A4. Expo does not support native module. you can read more expo caveats here

Q5. Why can't I run the iOS example? 'Failed to build iOS project. We ran "xcodebuild" command but it exited with error code 65.'
A5. Run the following commands in the project folder (e.g. react-native-pdf/example) to ensure that all dependencies are available:

yarn install (or npm install)
cd ios
pod install
cd ..
react-native run-ios

ChangeLog

ChangeLog details v6.7.5
  1. Added progressContainerStyle prop
  2. Improved: Added enableDoubleTapZoom option
  3. Fixed: Fix app crash with this.lastRNBFTask.cancel is not a function (#827)
  4. Fixed: Remove override to fix 'no matching methods to override' error (#822)

v6.7.4

  1. Fixed: fix Android crash issue

v6.7.3

  1. Fixed: fix android package name

v6.7.2

  1. Fixed: fix iOS double tap zoom scrolling
  2. Fixed: fix RN 73 compatibility
  3. Fixed: bump crypto-js to avoid critical vulnerability

v6.7.1

  1. Fixed: fix ios project setting
  2. Fixed: fix typo in RNPDFPdfViewManagerInterface interface causing android build error

v6.7.0

  1. Fixed: fix(iOS): center page at tap point after double tap to zoom
  2. Fixed: add PDFKit to podspec to make ios compile
  3. Improved: Update build.gradle to support RN 0.71 on new arch
  4. Fixed: fix some small bugs and documents.

v6.6.2

  1. Fixed: Migrate to ViewPropTypes exported from 'deprecated-react-native-prop-types'
  2. Added: Decode File Path for iOS
  3. Improved: prefer current page for calculating scale factor on fit

v6.6.1 depresed

v6.6.0 depresed

  1. Fixed: Migrate to ViewPropTypes exported from 'deprecated-react-native-prop-types'
  2. Added: Decode File Path for iOS
  3. Improved: prefer current page for calculating scale factor on fit
  4. Improved: Typescript version source

v6.5.0

  1. Fix: replace mavenCentral with maven
  2. Breaking Change(Android): replace deprecated repository: jcenter()
  3. Fix: loading progress
  4. Add: Typed "source" prop
  5. Remove: dependency to fbjs

v6.4.0

  1. Remove sample for reducing NPM package size
  2. Add support for setting a filename for the cached pdf file
  3. Use react-native-blob-util instead of rn-fetch-blob
  4. Add blob support
  5. remove progress-view dependency

v6.3.0

  1. Add windows support
  2. Fixed some bugs

[more]

Example

/**
 * Copyright (c) 2017-present, Wonday (@wonday.org)
 * All rights reserved.
 *
 * This source code is licensed under the MIT-style license found in the
 * LICENSE file in the root directory of this source tree.
 */

import React from 'react';
import { StyleSheet, Dimensions, View } from 'react-native';
import Pdf from 'react-native-pdf';

export default class PDFExample extends React.Component {
    render() {
        const source = { uri: 'http://samples.leanpub.com/thereactnativebook-sample.pdf', cache: true };
        //const source = require('./test.pdf');  // ios only
        //const source = {uri:'bundle-assets://test.pdf' };
        //const source = {uri:'file:///sdcard/test.pdf'};
        //const source = {uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."};
        //const source = {uri:"content://com.example.blobs/xxxxxxxx-...?offset=0&size=xxx"};
        //const source = {uri:"blob:xxxxxxxx-...?offset=0&size=xxx"};

        return (
            <View style={styles.container}>
                <Pdf
                    source={source}
                    onLoadComplete={(numberOfPages,filePath) => {
                        console.log(`Number of pages: ${numberOfPages}`);
                    }}
                    onPageChanged={(page,numberOfPages) => {
                        console.log(`Current page: ${page}`);
                    }}
                    onError={(error) => {
                        console.log(error);
                    }}
                    onPressLink={(uri) => {
                        console.log(`Link pressed: ${uri}`);
                    }}
                    style={styles.pdf}/>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'flex-start',
        alignItems: 'center',
        marginTop: 25,
    },
    pdf: {
        flex:1,
        width:Dimensions.get('window').width,
        height:Dimensions.get('window').height,
    }
});

Configuration

Property Type Default Description iOS Android Windows FirstRelease
source object not null PDF source like {uri:xxx, cache:false}. see the following for detail. <3.0
page number 1 initial page index <3.0
scale number 1.0 should minScale<=scale<=maxScale <3.0
minScale number 1.0 min scale 5.0.5
maxScale number 3.0 max scale 5.0.5
horizontal bool false draw page direction, if you want to listen the orientation change, you can use [react-native-orientation-locker] <3.0
showsHorizontalScrollIndicator bool true shows or hides the horizontal scroll bar indicator on iOS 6.6
showsVerticalScrollIndicator bool true shows or hides the vertical scroll bar indicator on iOS 6.6
scrollEnabled bool true enable or disable scroll 6.6
fitWidth bool false if true fit the width of view, can not use fitWidth=true together with scale <3.0, abandoned from 3.0
fitPolicy number 2 0:fit width, 1:fit height, 2:fit both(default) 3.0
spacing number 10 the breaker size between pages <3.0
password string "" pdf password, if password error, will call OnError() with message "Password required or incorrect password." <3.0
style object {backgroundColor:"#eee"} support normal view style, you can use this to set border/spacing color... <3.0
progressContainerStyle object {backgroundColor:"#eee"} support normal view style, you can use this to set border/spacing color... 6.9.0
renderActivityIndicator (progress) => Component when loading show it as an indicator, you can use your component <3.0
enableAntialiasing bool true improve rendering a little bit on low-res screens, but maybe course some problem on Android 4.4, so add a switch <3.0
enablePaging bool false only show one page in screen 5.0.1
enableRTL bool false scroll page as "page3, page2, page1" 5.0.1
enableAnnotationRendering bool true enable rendering annotation, notice:iOS only support initial setting,not support realtime changing 5.0.3
enableDoubleTapZoom bool true Enable double tap to zoom gesture 6.8.0
trustAllCerts bool true Allow connections to servers with self-signed certification 6.0.?
singlePage bool false Only show first page, useful for thumbnail views 6.2.1
onLoadProgress function(percent) null callback when loading, return loading progress (0-1) <3.0
onLoadComplete function(numberOfPages, path, {width, height}, tableContents) null callback when pdf load completed, return total page count, pdf local/cache path, {width,height} and table of contents ✔ but without tableContents <3.0
onPageChanged function(page,numberOfPages) null callback when page changed ,return current page and total page count <3.0
onError function(error) null callback when error happened <3.0
onPageSingleTap function(page) null callback when page was single tapped 3.0
onScaleChanged function(scale) null callback when scale page 3.0
onPressLink function(uri) null callback when link tapped 6.0.0

parameters of source

parameter Description default iOS Android Windows
uri pdf source, see the forllowing for detail. required
cache use cache or not false
cacheFileName specific file name for cached pdf file SHA1(uri) result
expiration cache file expired seconds (0 is not expired) 0
method request method when uri is a url "GET"
headers request headers when uri is a url {}

types of source.uri

Usage Description iOS Android Windows
{uri:"http://xxx/xxx.pdf"} load pdf from a url
{require("./test.pdf")} load pdf relate to js file (do not need add by xcode)
{uri:"bundle-assets://path/to/xxx.pdf"} load pdf from assets, the file should be at android/app/src/main/assets/path/to/xxx.pdf
{uri:"bundle-assets://xxx.pdf"} load pdf from assets, you must add pdf to project by xcode. this does not support folder.
{uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."} load pdf from base64 string
{uri:"file:///absolute/path/to/xxx.pdf"} load pdf from local file system
{uri:"ms-appx:///xxx.pdf"}} load pdf bundled with UWP app
{uri:"content://com.example.blobs/xxxxxxxx-...?offset=0&size=xxx"} load pdf from content URI ✔*
{uri:"blob:xxxxxxxx-...?offset=0&size=xxx"} load pdf from blob URL

*) requires building React Native from source with this patch

Methods

Methods operate on a ref to the PDF element. You can get a ref with the following code:

return (
  <Pdf
    ref={(pdf) => { this.pdf = pdf; }}
    source={source}
    ...
  />
);

setPage()

setPage(pageNumber)

Set the current page of the PDF component. pageNumber is a positive integer. If pageNumber > numberOfPages, current page is not changed.

Example:

this.pdf.setPage(42); // Display the answer to the Ultimate Question of Life, the Universe, and Everything

react-native-pdf's People

Contributors

alpha0010 avatar alvinkoh avatar bavuongco10 avatar bzoz avatar dlinds avatar gadhiyamanan avatar gauthierm avatar hhunaid avatar ishigamii avatar j-piasecki avatar jaimecbernardo avatar jfaris avatar jiansheng-gt avatar keremoge avatar luutruong avatar marksturm avatar mateusz1913 avatar matthieulemoine avatar mrshahzeb7 avatar nicklammertyn avatar pradeepmdk avatar r0b0t3d avatar relax594 avatar serra19 avatar shllg avatar tomekzaw avatar uokesita avatar vikas5914 avatar wolewicki avatar wonday avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-pdf's Issues

Strange behaviors in iOS

I have some issues that are just happening in iOS. Android works just fine.

  1. When zooming, the view resets to the center. This means that if I move around the pdf and then try to zoom in or out, I get back to the center every time.
  2. The speed when panning is super slow.
  3. When zooming out until you can see the pdf, it does some weird wiggles, like moving up and down. Solved in #59

Thanks!

Display base64 pdf on ios platform

I have base64 encoded pdf.
I use source = {uri : "data:application/pdf;base64,"}
I can successfully view it on Android. However when run application on ios I see black screen.
In log there is a message:
write base64 to file:/Users/...../Library/Caches/.pdf
but when I check that location I cannot see any file

Thanks for help )

Crash when working with Base64 file

When i try to load a base64 string i get this error (tryied only on iOS)

  "message": "_reactNativeFetchBlob2.default.fs.writeFile(...).progress is not a function",
  "stack": [
    {
      "functionName": "Pdf._this._prepareFile",
      "lineNumber": 117,
      "columnNumber": 11,
      "fileName": "node_modules/react-native-pdf/index.js"
    },
    {
      "functionName": "Pdf._this._loadFromSource",
      "lineNumber": 80,
      "columnNumber": 11,
      "fileName": "node_modules/react-native-pdf/index.js"
    },
    {
      "functionName": "Pdf.componentDidMount",
      "lineNumber": 46,
      "columnNumber": 9,
      "fileName": "node_modules/react-native-pdf/index.js"
    },
    {
      "functionName": "Pdf.proxiedComponentDidMount",
      "lineNumber": 61,
      "columnNumber": 39,
      "fileName": "node_modules/react-proxy/modules/createPrototypeProxy.js"
    },
    {
      "functionName": null,
      "lineNumber": 1658,
      "columnNumber": 28,
      "fileName": "node_modules/react-native/Libraries/Renderer/ReactNativeStack-dev.js"
    },
    {
      "functionName": "measureLifeCyclePerf",
      "lineNumber": 1610,
      "columnNumber": 15,
      "fileName": "node_modules/react-native/Libraries/Renderer/ReactNativeStack-dev.js"
    },
    {
      "functionName": null,
      "lineNumber": 1657,
      "columnNumber": 12,
      "fileName": "node_modules/react-native/Libraries/Renderer/ReactNativeStack-dev.js"
    },
    {
      "functionName": "CallbackQueue.notifyAll",
      "lineNumber": 2121,
      "columnNumber": 102,
      "fileName": "node_modules/react-native/Libraries/Renderer/ReactNativeStack-dev.js"
    },
    {
      "functionName": "ReactNativeReconcileTransaction.close",
      "lineNumber": 2138,
      "columnNumber": 29,
      "fileName": "node_modules/react-native/Libraries/Renderer/ReactNativeStack-dev.js"
    },
    {
      "functionName": "ReactNativeReconcileTransaction.closeAll",
      "lineNumber": 1412,
      "columnNumber": 96,
      "fileName": "node_modules/react-native/Libraries/Renderer/ReactNativeStack-dev.js"
    }
  ]
}

My actual code

	render() {
		let source = {uri:"data:application/pdf;base64,JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlL1hPYmplY3QvQ29sb3JTcGFjZS9EZXZpY2VSR0IvU3VidHlwZS9JbWFnZS9CaXRzUGVyQ29tcG9uZW50IDgvV2lkdGggMjU1L0xlbmd0aCAxNTUyNi9IZWlnaHQgMTI4L0ZpbHRlci9EQ1REZWNvZGU+PnN0cmVhbQr/2P/hABhFeGlmAABJSSoACAAAAAAAAAAAAAAA/+wAEUR1Y2t5AAEABAAAADwAAP/hAytodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjJDQkNFNEEzODREMTFFNjk4QTRBMUZFN0RFMkNGMzAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjJDQkNFNDkzODREMTFFNjk4QTRBMUZFN0RFMkNGMzAiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmRpZDozNzQ1QUI5RDREMzhFNjExQkYyNURDODlBRTkwMDkxRCIgc3RSZWY6ZG9jdW1l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agoxIDAgb2JqCjw8L0dyb3VwPDwvVHlwZS9Hcm91cC9DUy9EZXZpY2VSR0IvUy9UcmFuc3BhcmVuY3k+Pi9QYXJlbnQgNiAwIFIvQ29udGVudHMgNSAwIFIvVHlwZS9QYWdlL1Jlc291cmNlczw8L1hPYmplY3Q8PC9pbWcwIDMgMCBSPj4vUHJvY1NldCBbL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSV0vQ29sb3JTcGFjZTw8L0NTL0RldmljZVJHQj4+L0ZvbnQ8PC9GMSAyIDAgUi9GMiA0IDAgUj4+Pj4vTWVkaWFCb3hbMCAwIDU5NSA4NDJdPj4KZW5kb2JqCjcgMCBvYmoKWzEgMCBSL1hZWiAwIDg1MiAwXQplbmRvYmoKMiAwIG9iago8PC9CYXNlRm9udC9IZWx2ZXRpY2EvVHlwZS9Gb250L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9TdWJ0eXBlL1R5cGUxPj4KZW5kb2JqCjQgMCBvYmoKPDwvQmFzZUZvbnQvSGVsdmV0aWNhLUJvbGQvVHlwZS9Gb250L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9TdWJ0eXBlL1R5cGUxPj4KZW5kb2JqCjYgMCBvYmoKPDwvSVRYVCgyLjEuNykvVHlwZS9QYWdlcy9Db3VudCAxL0tpZHNbMSAwIFJdPj4KZW5kb2JqCjggMCBvYmoKPDwvTmFtZXNbKEpSX1BBR0VfQU5DSE9SXzBfMSkgNyAwIFJdPj4KZW5kb2JqCjkgMCBvYmoKPDwvRGVzdHMgOCAwIFI+PgplbmRvYmoKMTAgMCBvYmoKPDwvTmFtZXMgOSAwIFIvVHlwZS9DYXRhbG9nL1ZpZXdlclByZWZlcmVuY2VzPDwvUHJpbnRTY2FsaW5nL0FwcERlZmF1bHQ+Pi9QYWdlcyA2IDAgUj4+CmVuZG9iagoxMSAwIG9iago8PC9DcmVhdG9yKEphc3BlclJlcG9ydHMgTGlicmFyeSB2ZXJzaW9uIDUuNS4yKS9Qcm9kdWNlcihpVGV4dCAyLjEuNyBieSAxVDNYVCkvTW9kRGF0ZShEOjIwMTcxMDA0MTQzMjM3KzAyJzAwJykvQ3JlYXRpb25EYXRlKEQ6MjAxNzEwMDQxNDMyMzcrMDInMDAnKT4+CmVuZG9iagp4cmVmCjAgMTIKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDE2MjAyIDAwMDAwIG4gCjAwMDAwMTY1MDMgMDAwMDAgbiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDE2NTkxIDAwMDAwIG4gCjAwMDAwMTU2OTYgMDAwMDAgbiAKMDAwMDAxNjY4NCAwMDAwMCBuIAowMDAwMDE2NDY4IDAwMDAwIG4gCjAwMDAwMTY3NDcgMDAwMDAgbiAKMDAwMDAxNjgwMSAwMDAwMCBuIAowMDAwMDE2ODMzIDAwMDAwIG4gCjAwMDAwMTY5MzcgMDAwMDAgbiAKdHJhaWxlcgo8PC9Sb290IDEwIDAgUi9JRCBbPDI2ODIxMjAxZTc4NThhMGJhNzY0YTQ2ZmM0ZmQ1NTg4PjxiMTdlZmFhZjI0NDNiMmVkZGFjNDc4ZDk2YjZmOThhMD5dL0luZm8gMTEgMCBSL1NpemUgMTI+PgpzdGFydHhyZWYKMTcxMDUKJSVFT0YK"};
		return (
			<View style={styles.mainContainer}>
				<Pdf ref={(pdf)=>{this.pdf = pdf;}}
					 source={source}
					 horizontal={false}
					 onLoadComplete={(pageCount)=>{
						 this.setState({pageCount: pageCount});
						 console.log(`total page count: ${pageCount}`);
					 }}
					 onPageChanged={(page,pageCount)=>{
						 this.setState({page:page});
						 console.log(`current page: ${page}`);
					 }}
					 onError={(error)=>{
						 console.log(error);
					 }}
					 style={styles.pdf}/>
			</View>
		)
	}

Request: Thumbnails

Im a poor beginner with react native and i just made some test with it. But as far as i was able to see, i love your work :-) but i wonder if it would be possible to have thumbnails for faster pagepicking, like they made it here:
screenshot_20170829-141630

iOS scrolling animation problem

Hi Author,

I am coming to you again, sorry for alway annoying you those issue.
There are some animation error during quick swipe page. This pdf file only contains 2 pages, but when I swipe quick to change the page, it shows like scroll the page for many times. Is it possible fix that?

I have tested that on real device, it has same issue. However, it is working perfectly in android.

Issue as the gif shows:
untitled

could not open the pdf

Has any prerequisite?such as: react native version.. work on "react-native": "0.42.3",

Password Protected PDF

giving error when render password protected pdf !!! how to render password protected pdf

Feature: Links within PDFs

Ive successfully integrated the viewer into an application and the pdfs all render as expected. I would love to be able to let the users press the hyperlinks. Looking at the props and the viewer it doesn't look like this is currently possible. Is this something you have looked into at all?

Deprecated Warnings

When I want to open pdf from other url in Android, I got deprecated warnings. My RN is 0.43

"Warning: You are manually calling a React.PropTypes validation funtion for the 'indeterminate' prop on 'ProgressBarAndroid'. This is deprecated and will not work in production with the next major version."

Horizontal Pagination ?

hi @wonday ,
i've checked any other issues
I'm sorry if this is a duplicate, i hope not.

i've tried spacing props to set page breaker. Its working perfectly, thanks

I want to ask a question,
when i use horizontal = true, it's still plain scrolling between the pages
I wonder, is there any method to implement pagination ? So user will have to swipe once (to the right / left), then it will scroll the screen and stop right at the next/previous page.

Its hard to explain. But if you've tried React Native's Scrollview / Flatlist using horizontal = true and pagingEnabled = true,
Or, if you've tried react-native-tabs to swipe over tabs, then you'll understand what i mean

(reference : https://facebook.github.io/react-native/docs/scrollview.html#pagingenabled)

My Question is, is there any way to add pagination to this library ?
So, users will experience like they are reading a real book.

If it's not available yet, its okay... but i think it's a great challenge for the collaburators, even myself

Thanks :)

Integration

Hi,
I'm tring to integrate with a pre existing app using Native Starter Pro (http://gitstrap.com/strapmobile/NativeStarterPro) and have an issue displaying pdf as shown below. The first page of pdf displays but the next prev buttons are not enabled.Swiping page up and down works and as soon as i swipe down one page the prev button works, the next never works however.
TIA
John

import React, { Component } from 'react';
// import { Image } from 'react-native';
import { Image, ListView, StyleSheet, Dimensions, TouchableHighlight, View, Text } from 'react-native';

import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import { Container, Header, Title, Icon, Left, Right, Button, Body } from 'native-base';
// , Content, Button, Icon, Left, Right, Body, ListItem } from 'native-base';

import { openDrawer } from '../../actions/drawer';
// import styles from './styles';

import Pdf from 'react-native-pdf';

const glow2 = require('../../../images/glow2.png');

class Lists extends Component {

static propTypes = {
openDrawer: React.PropTypes.func,
}
constructor(props) {
super(props);
this.state = {
page: 1,
pageCount: 1,
};
this.pdf = null;
this.source = { uri: 'http://samples.leanpub.com/thereactnativebook-sample.pdf', cache: false };

}

componentDidMount() {
}
prePage = () => {
if (this.pdf) {
let prePage = this.state.page > 1 ? this.state.page - 1 : 1;
this.pdf.setNativeProps({ page: prePage });
this.setState({ page: prePage });
console.log(prePage: ${prePage});
}
}

nextPage = () => {
if (this.pdf) {
let nextPage = this.state.page + 1 > this.state.pageCount ? this.state.pageCount : this.state.page + 1;
this.pdf.setNativeProps({ page: nextPage });
this.setState({ page: nextPage });
console.log(nextPage: ${nextPage});
}

}
render() {
// let source = {uri:'http://samples.leanpub.com/thereactnativebook-sample.pdf',cache:true};

return (
  <Container style={{ backgroundColor: '#384850' }}>
    <Image source={glow2} style={styles.containerO} >
      <Header>
        <Left>
          <Button transparent onPress={() => Actions.pop()}>
            <Icon name="ios-arrow-back" style={{ fontSize: 30, lineHeight: 32 }} />
          </Button>
        </Left>
        <Body>
          <Title>List</Title>
        </Body>
        <Right>
          <Button transparent onPress={this.props.openDrawer}>
            <Icon name="ios-menu" style={{ fontSize: 30, lineHeight: 32 }} />
          </Button>
        </Right>
      </Header>
      <View style={styles.container}>
        <View style={{ flexDirection: 'row' }}>
          <TouchableHighlight disabled={this.state.page == 1} style={this.state.page == 1 ? styles.btnDisable : styles.btn} onPress={() => this.prePage()}>
            <Text style={styles.btnText}>{'Previous'}</Text>
          </TouchableHighlight>
          <TouchableHighlight disabled={this.state.page == this.state.pageCount} style={this.state.page == this.state.pageCount ? styles.btnDisable : styles.btn} onPress={() => this.nextPage()}>
            <Text style={styles.btnText}>{'Next'}</Text>
          </TouchableHighlight>
       

        </View>
        <Pdf ref={(pdf) => { this.pdf = pdf; }}
          source={this.source}
          page={1}
          scale={1}
          horizontal={false}
          onLoadComplete={(pageCount) => {
            this.setState({ pageCount: pageCount });
            console.log(`total page count: ${pageCount}`);
          }}
          onPageChanged={(page, pageCount) => {
            this.setState({ page: page });
            console.log(`current page: ${page}`);
          }}
          onError={(error) => {
            console.log(error);
          }}
          style={styles.pdf} />
      </View>
    </Image>
  </Container>
)

}
}

function bindAction(dispatch) {
return {
openDrawer: () => dispatch(openDrawer()),
};
}

export default connect(null, bindAction)(Lists);

const styles = StyleSheet.create({
containerO: {
flex: 1,
width: null,
height: null,
},
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
marginTop: 25,
},
btn: {
margin: 5,
padding: 5,
backgroundColor: "blue",
},
btnDisable: {
margin: 5,
padding: 5,
backgroundColor: "gray",
},
btnText: {
color: "#FFF",
},
pdf: {
flex: 1,
width: Dimensions.get('window').width,
}
});

import React, { Component } from 'react';
// import { Image } from 'react-native';
import { Image, ListView, StyleSheet, Dimensions, TouchableHighlight, View, Text } from 'react-native';

import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import { Container, Header, Title, Icon, Left, Right, Button, Body } from 'native-base';
// , Content, Button, Icon, Left, Right, Body, ListItem } from 'native-base';

import { openDrawer } from '../../actions/drawer';
// import styles from './styles';

import Pdf from 'react-native-pdf';

const glow2 = require('../../../images/glow2.png');

class Lists extends Component {

static propTypes = {
openDrawer: React.PropTypes.func,
}
constructor(props) {
super(props);
this.state = {
page: 1,
pageCount: 1,
};
this.pdf = null;
this.source = { uri: 'http://samples.leanpub.com/thereactnativebook-sample.pdf', cache: false };

}

componentDidMount() {
}
prePage = () => {
if (this.pdf) {
let prePage = this.state.page > 1 ? this.state.page - 1 : 1;
this.pdf.setNativeProps({ page: prePage });
this.setState({ page: prePage });
console.log(prePage: ${prePage});
}
}

nextPage = () => {
if (this.pdf) {
let nextPage = this.state.page + 1 > this.state.pageCount ? this.state.pageCount : this.state.page + 1;
this.pdf.setNativeProps({ page: nextPage });
this.setState({ page: nextPage });
console.log(nextPage: ${nextPage});
}

}
render() {
// let source = {uri:'http://samples.leanpub.com/thereactnativebook-sample.pdf',cache:true};

return (
  <Container style={{ backgroundColor: '#384850' }}>
    <Image source={glow2} style={styles.containerO} >
      <Header>
        <Left>
          <Button transparent onPress={() => Actions.pop()}>
            <Icon name="ios-arrow-back" style={{ fontSize: 30, lineHeight: 32 }} />
          </Button>
        </Left>
        <Body>
          <Title>List</Title>
        </Body>
        <Right>
          <Button transparent onPress={this.props.openDrawer}>
            <Icon name="ios-menu" style={{ fontSize: 30, lineHeight: 32 }} />
          </Button>
        </Right>
      </Header>
      <View style={styles.container}>
        <View style={{ flexDirection: 'row' }}>
          <TouchableHighlight disabled={this.state.page == 1} style={this.state.page == 1 ? styles.btnDisable : styles.btn} onPress={() => this.prePage()}>
            <Text style={styles.btnText}>{'Previous'}</Text>
          </TouchableHighlight>
          <TouchableHighlight disabled={this.state.page == this.state.pageCount} style={this.state.page == this.state.pageCount ? styles.btnDisable : styles.btn} onPress={() => this.nextPage()}>
            <Text style={styles.btnText}>{'Next'}</Text>
          </TouchableHighlight>
          <TouchableHighlight style={styles.btn} onPress={() => this.nextPage()}>
            <Text style={styles.btnText}>{'Next'}</Text>
          </TouchableHighlight>

        </View>
        <Pdf ref={(pdf) => { this.pdf = pdf; }}
          source={this.source}
          page={1}
          scale={1}
          horizontal={false}
          onLoadComplete={(pageCount) => {
            this.setState({ pageCount: pageCount });
            console.log(`total page count: ${pageCount}`);
          }}
          onPageChanged={(page, pageCount) => {
            this.setState({ page: page });
            console.log(`current page: ${page}`);
          }}
          onError={(error) => {
            console.log(error);
          }}
          style={styles.pdf} />
      </View>
    </Image>
  </Container>
)

}
}

function bindAction(dispatch) {
return {
openDrawer: () => dispatch(openDrawer()),
};
}

export default connect(null, bindAction)(Lists);

const styles = StyleSheet.create({
containerO: {
flex: 1,
width: null,
height: null,
},
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
marginTop: 25,
},
btn: {
margin: 5,
padding: 5,
backgroundColor: "blue",
},
btnDisable: {
margin: 5,
padding: 5,
backgroundColor: "gray",
},
btnText: {
color: "#FFF",
},
pdf: {
flex: 1,
width: Dimensions.get('window').width,
}
});

import React, { Component } from 'react';
// import { Image } from 'react-native';
import { Image, ListView, StyleSheet, Dimensions, TouchableHighlight, View, Text } from 'react-native';

import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import { Container, Header, Title, Icon, Left, Right, Button, Body } from 'native-base';
// , Content, Button, Icon, Left, Right, Body, ListItem } from 'native-base';

import { openDrawer } from '../../actions/drawer';
// import styles from './styles';

import Pdf from 'react-native-pdf';

const glow2 = require('../../../images/glow2.png');

class Lists extends Component {

static propTypes = {
openDrawer: React.PropTypes.func,
}
constructor(props) {
super(props);
this.state = {
page: 1,
pageCount: 1,
};
this.pdf = null;
this.source = { uri: 'http://samples.leanpub.com/thereactnativebook-sample.pdf', cache: false };

}

componentDidMount() {
}
prePage = () => {
if (this.pdf) {
let prePage = this.state.page > 1 ? this.state.page - 1 : 1;
this.pdf.setNativeProps({ page: prePage });
this.setState({ page: prePage });
console.log(prePage: ${prePage});
}
}

nextPage = () => {
if (this.pdf) {
let nextPage = this.state.page + 1 > this.state.pageCount ? this.state.pageCount : this.state.page + 1;
this.pdf.setNativeProps({ page: nextPage });
this.setState({ page: nextPage });
console.log(nextPage: ${nextPage});
}

}
render() {
// let source = {uri:'http://samples.leanpub.com/thereactnativebook-sample.pdf',cache:true};

return (
  <Container style={{ backgroundColor: '#384850' }}>
    <Image source={glow2} style={styles.containerO} >
      <Header>
        <Left>
          <Button transparent onPress={() => Actions.pop()}>
            <Icon name="ios-arrow-back" style={{ fontSize: 30, lineHeight: 32 }} />
          </Button>
        </Left>
        <Body>
          <Title>List</Title>
        </Body>
        <Right>
          <Button transparent onPress={this.props.openDrawer}>
            <Icon name="ios-menu" style={{ fontSize: 30, lineHeight: 32 }} />
          </Button>
        </Right>
      </Header>
      <View style={styles.container}>
        <View style={{ flexDirection: 'row' }}>
          <TouchableHighlight disabled={this.state.page == 1} style={this.state.page == 1 ? styles.btnDisable : styles.btn} onPress={() => this.prePage()}>
            <Text style={styles.btnText}>{'Previous'}</Text>
          </TouchableHighlight>
          <TouchableHighlight disabled={this.state.page == this.state.pageCount} style={this.state.page == this.state.pageCount ? styles.btnDisable : styles.btn} onPress={() => this.nextPage()}>
            <Text style={styles.btnText}>{'Next'}</Text>
          </TouchableHighlight>
          <TouchableHighlight style={styles.btn} onPress={() => this.nextPage()}>
            <Text style={styles.btnText}>{'Next'}</Text>
          </TouchableHighlight>

        </View>
        <Pdf ref={(pdf) => { this.pdf = pdf; }}
          source={this.source}
          page={1}
          scale={1}
          horizontal={false}
          onLoadComplete={(pageCount) => {
            this.setState({ pageCount: pageCount });
            console.log(`total page count: ${pageCount}`);
          }}
          onPageChanged={(page, pageCount) => {
            this.setState({ page: page });
            console.log(`current page: ${page}`);
          }}
          onError={(error) => {
            console.log(error);
          }}
          style={styles.pdf} />
      </View>
    </Image>
  </Container>
)

}
}

function bindAction(dispatch) {
return {
openDrawer: () => dispatch(openDrawer()),
};
}

export default connect(null, bindAction)(Lists);

const styles = StyleSheet.create({
containerO: {
flex: 1,
width: null,
height: null,
},
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
marginTop: 25,
},
btn: {
margin: 5,
padding: 5,
backgroundColor: "blue",
},
btnDisable: {
margin: 5,
padding: 5,
backgroundColor: "gray",
},
btnText: {
color: "#FFF",
},
pdf: {
flex: 1,
width: Dimensions.get('window').width,
}
});
simulator screen shot jul 5 2017 12 33 43 pm

simulator screen shot jul 5 2017 12 35 02 pm

How to detect password protected PDF

Thanks for your great library,

Your library supports password protected pdf file but I don't know how to detect it/
For example, user got a password protected pdf file and we cannot know the password. If I use with default setting (password is "") to open then it will show only the blank page (caused by wrong password).
I tried checking onError callback function but it did not fire.
It would be better if you show a popup that force user to input password.
Looking forward to your reply
Thanks

Scrolling stacked when the zoom in.

Hey bro,

Thanks for you quick fixed the onLoadComplete bug. And then i found the scrolling will stacked in iOS if scale is not big enough. Which is meaning the page cannot be fully showed up, the edge of page will be cut off. But if continuously zoom in, the page could be showed correctly.

scale around 1.5 (the corner has been cut):
simulator screen shot 11 jul 2017 10 37 12

scale > 2 is showed correct:
simulator screen shot 11 jul 2017 10 37 20

*Android is working perfectly.

ios scroll control invalid

On ios, when the page is scrolling, I tap the screen to stop scroll, but it doesn't work. Is it my problem when I integrate the package? Or some config error when I use it?

Thanks.

after link module fetch-blob can't build app on android

react-native 0.43.0
I'm did the commands

npm install react-native-pdf --save 
react-native link react-native-pdf
npm install react-native-fetch-blob --save
// builds good
react-native link react-native-fetch-blob
or 
RNFB_ANDROID_PERMISSIONS=true react-native link react-native-fetch-blob

after link react-native-fetch-blob and trying build I have following error
http://prntscr.com/gnik8y
ios works good

Error: "Unable to resolve module `AccessibilityInfo`" after upgrading to 1.3.1

After upgrading to version 1.3.1 I'm getting this error both on Android and iOS builds.
I had to go back to 1.3.0 in the meantime.

Unable to resolve module `AccessibilityInfo` from `/Users/ci/agent/vstsagent/_work/1/s/InfotycoonMobile/node_modules/react-native/Libraries/react-native/react-native-implementation.js`: Module does not exist in the module map or in these directories:
  /Users/ci/agent/vstsagent/_work/1/s/InfotycoonMobile/node_modules/react-native/node_modules
,   /Users/ci/agent/vstsagent/_work/1/s/InfotycoonMobile/node_modules
,   /Users/ci/agent/vstsagent/_work/node_modules

This might be related to https://github.com/facebook/react-native/issues/4968
To resolve try the following:
  1. Clear watchman watches: `watchman watch-del-all`.
  2. Delete the `node_modules` folder: `rm -rf node_modules && npm install`.
  3. Reset packager cache: `rm -fr $TMPDIR/react-*` or `npm start -- --reset-cache`.

I have cleaned npm cache, deleted node modules and deleted temp files from packager. This happens also on the CI environment which always starts fresh.

My package.json looks like this:

"dependencies": {
    "axios": "^0.16.2",
    "lodash": "^4.17.4",
    "mobile-center": "^0.7.0",
    "mobile-center-analytics": "^0.7.0",
    "mobile-center-crashes": "^0.7.0",
    "mobile-center-push": "^0.7.0",
    "moment": "^2.18.1",
    "native-base": "2.2.0",
    "react": "16.0.0-alpha.6",
    "react-native": "0.44.3",
    "react-native-accordion": "compojoom/react-native-accordion.git#compojoom-fixes",
    "react-native-couchbase-lite": "^0.6.0",
    "react-native-datepicker": "^1.6.0",
    "react-native-device-info": "^0.10.2",
    "react-native-fetch-blob": "^0.10.8",
    "react-native-fs": "^2.3.3",
    "react-native-image-crop-picker": "0.15.1",
    "react-native-mail": "^3.0.4",
    "react-native-pdf": "1.3.0",
    "react-native-popover-tooltip": "^1.0.6",
    "react-native-router-flux": "3.39.2",
    "react-native-signature-capture": "^0.4.6",
    "react-native-tab-view": "0.0.67",
    "react-native-vector-icons": "^4.2.0",
    "react-native-zip-archive": "^2.0.0",
    "react-tween-state": "^0.1.5",
    "react-native-permissions": "1.0.0"
  },
  "devDependencies": {
    "babel-jest": "20.0.3",
    "babel-plugin-module-resolver": "^2.7.1",
    "babel-preset-react-native": "1.9.2",
    "jest": "20.0.4",
    "react-test-renderer": "16.0.0-alpha.6"
}

Is this a bug or am I missing some step for this version?

iOS Scrolling Issues

I'm using NativeBase for components, my <View> is wrapped in a <Container>. I'm loading large PDFs, 200+ pages with the PDF's loaded in the local app directory. When I scroll quickly and continue to scroll before the scrolling animation is completed, the pages look glitchy. If I tap on the document as its scrolling, it doesn't seem like it stops the scroll. If I scroll up while it's scrolling down then it seems to stop it.

"dependencies": {
"native-base": "^2.3.2",
"react": "16.0.0-alpha.12",
"react-native": "0.48.4",
"react-native-fetch-blob": "^0.10.8",
"react-native-pdf": "^1.3.3",
"react-navigation": "^1.0.0-beta.13"
},

pdf-scroll-issue2

pdf-scroll-issue3

打不开PDF文件

文件路径是这个样子的:file:///sdcard/Download/PDFFlies.pdf
输出 1 和 Load pdf failed,
这个是啥原因呢,

"react-native-pdf": "^1.2.8",
"react-native": "0.47.1",
"react-native-fs": "^2.5.1",
谢谢呐

PropTypes warning

Hi,

I am seeing the PropTypes warning when following the same code as shown in the example in the README.

I see that there was an issue raised before and a PR was merged here: #22

Is the package not published with those changes? or is there another issue?

installation

Hi.
While I have no problems with IOS with the exact setup I've tried to install on a few windows 10 comptuters with RN 0.41 and get the following error
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\React\nsp\NSPV6\NativeStarterPro-v6.0.0>npm install react-native-pdf --save
[email protected] node_modules\react-native-pdf
├── [email protected]
└── [email protected] ([email protected])

C:\React\nsp\NSPV6\NativeStarterPro-v6.0.0>react-native link react-native-pdf
rnpm-install info Linking react-native-pdf android dependency
rnpm-install ERR! It seems something went wrong while linking. Error: ENOENT: no such file or directory, open 'C:\React\nsp\NSPV6\NativeStarterPro-v6.0.0\android\app\src\main\java\android\support\v7\appcompat\MainApplication.java'
Please file an issue here: https://github.com/facebook/react-native/issues

ENOENT: no such file or directory, open 'C:\React\nsp\NSPV6\NativeStarterPro-v6.0.0\android\app\src\main\java\android\support\v7\appcompat\MainApplication.java'

I have no problem installing and running your eample on the same win 10 computers, a bit lost.

John

How to dynamically load PDF source

Environment:
OS: macOS Sierra 10.12.6
Node: 6.11.3
Yarn: 1.0.2
npm: 5.3.0
Watchman: 4.9.0
Xcode: Xcode 8.3.3 Build version 8E3004b
Android Studio: Not Found

Packages: (wanted => installed)
react: 16.0.0-alpha.12 => 16.0.0-alpha.12
react-native: 0.48.4 => 0.48.4
"react-native-fetch-blob": "^0.10.8",
"react-native-pdf": "^1.3.3"

How can I dynamically display a PDF using variables?

I am able to successfully load the PDF if I enter the URL in the code, however I want to dynamically load a PDF based on the user's selection.

For example, I have a list of PDFs. When the user clicks one, I open a Modal with the PDF viewer in it. I want to set the state for the PDF URL (which is a local asset) and load it. When I use variables, it doesn't work. Is there a way to get it to work?

Thanks in advance.

How to import it in swift project(has pod file) ?

How to import it in swift project(has pod file) ?My ios project is Swift ,i tried link libraries way,but it has error:
<React/RCTBridge.h> not found!
maybe i use pod's " user_framework",but i must have it.....
please help me.thanks.

android sometimes can not open pdf

在1.0.9版本中,android可以打开pdf文件,ios端如果只有1页,则也可以滑动;更新到最新版本1.2.6时,android多次打开同一个pdf,出现了经常性打开空白文档,加载不了内容,我回退到1.0.9又可以正常加载pdf了,希望作者可以修复下这一bug;而且android的加载进度条变成了横条,无进度显示,样式没有之前的loading转圈好

Not able to access PDF if the URL require Authorization

I noticed that in Android version, when trying to download the file that contain Authorization header wont work.

This only happen in Android, iOS seem to take in headers from other calls.

Is there a way for you to add optional prop (HTTP HEADERS) and if there exist add the headers into this blick

this.lastRNBFTask = RNFetchBlob
            .config({
                // response data will be saved to this path if it has access right.
                path: cacheFile
            })
            .fetch('GET', url, {
                //some headers ..
               {this.props.http_headers}
            
            });

Pan doesn't work in direction of page change [iOS]

<PDF
    style={{flex: 1, backgroundColor: 'white'}}
    source={{uri: 'myfile.pdf', cache: true}}
    page={1}
/>

If I pinch-zoom this view, I cannot move pdf "inside it" up and down, but can horizontally. If I pass horizontal={true} prop, then it stops moving left-right, but vertical pan starts working well. On a side note, maybe there could be a enableGestureDraw={true} prop, which would allow passing false and disabling annoying bouncing on one-page documents?

onLoadComplete Is not working

Hey there,

I have try the example code from ReadMe, and I think onLoadComplete is not working. But onPageChanged has the pageCount as callback, it is working fine for general propose.

Handle back button on Android

Hi, I'm using your library with success but I'd like to be able to control the "back" arrow at the top as well as the back button (on Android).

I can't see where this is done. Could you please confirm?

Thanks!
Ben

package is only working in debug mode

pdf view is only show in debug mode and need to always run the "react-native start" command.

If I stop or unplug, viewer is only showing loading indicator. I am reading the file from project folder.

<Pdf ref={(pdf)=>{this.pdf = pdf;}} source={require("dicalaws/pdf/en/0.pdf")} page={1} horizontal={false} onLoadComplete={(pageCount)=>{ this.setState({pageCount: pageCount}); console.log(total page count: ${pageCount}); }} onPageChanged={(page,pageCount)=>{ this.setState({page:page}); console.log(current page: ${page});}} style={styles.pdf}/>

Regards,
Alex Aung

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.