flutter_fullpdfview 1.0.8+1

  • Readme
  • Changelog
  • Example
  • Installing
  • 86

flutter_fullpdfview #

Native PDF View for iOS and Android

Use this package as a library #

1. Depend on it #

Add this to your package's pubspec.yaml file:

dependencies:
  flutter_fullpdfview: latest_version

2. Install it #

You can install packages from the command line:

with Flutter:

$ flutter packages get

Alternatively, your editor might support pub get or flutter packages get. Check the docs for your editor to learn more.

3. Setup #

iOS

Opt-in to the embedded views preview by adding a boolean property to the app's Info.plist file with the key io.flutter.embedded_views_preview and the value YES.

4. Import it #

Now in your Dart code, you can use:

import 'package:flutter_fullpdfview/flutter_fullpdfview.dart';

Options #

NameAndroidiOS
onViewCreated
onRender
onPageChanged
onError
onPageError
gestureRecognizers
filePath
fitEachPage
defaultPage
dualPageMode
enableSwipe
swipeHorizontal
password
nightMode
password
autoSpacing
pageFling
pageSnap
backgroundColor
fitPolicy

Only black and white are supported on Android and iOS at the moment!

Controller Options #

NameDescriptionParametersReturn
getPageCountGet total page count-Future<int>
getCurrentPageGet current page-Future<int>
setPageGo to/Set pageint pageFuture<bool>
setPageWithAnimationGo to/Set pageint pageFuture<bool>
resetZoomGo page and fitToWidthint pageFuture<bool>
getZoomGet the current zoomdouble zoomFuture<double>
getPageWidthGet the pdf widthdouble widthFuture<double>
getPageHeightGet the pdf heightdouble heightFuture<double>

Example #

PDFView(
  filePath: path,
  enableSwipe: true,
  fitEachPage: true,
  swipeHorizontal: true,
  autoSpacing: false,
  pageFling: false,
  defaultPage: 8,
  dualPageMode: orientation == Orientation.landscape
  onRender: (_pages) {
    setState(() {
      pages = _pages;
      isReady = true;
    });
  },
  onError: (error) {
    print(error.toString());
  },
  onPageError: (page, error) {
    print('$page: ${error.toString()}');
  },
  onViewCreated: (PDFViewController pdfViewController) {
    _controller.complete(pdfViewController);
  },
  onPageChanged: (int page, int total) {
    print('page change: $page/$total');
  },
),

For production usage #

If you use proguard, you should include this line.

-keep class com.shockwave.**

Dependencies #

Android #

apv Updated From: AndroidPdfViewer

iOS (only support> 11.0) #

PDFKit

1.0.8+1 #

Fixing IOS Class, view is now rendered correctly

1.0.7+8 #

Update apv version

1.0.7+7 #

Fix resetZoom to take snapEdge in account, using zoomToWithAnimation to do so

1.0.7+6 #

Updating apv version

1.0.7+5 #

Updating apv version

1.0.7+4 #

Updating apv version

1.0.7+3 #

Fixing ios default Page

1.0.7+2 #

Fixing dualPageMode for ios, scale calculation wasn't accurate

1.0.7+1 #

Updating APV version to 1.3.1, snapEdge was missing in startXAnimation so the page is centered in screen when using jumpTo()

1.0.6+7 #

Android resetZoom

1.0.6+6 #

Adding fit policy to both on ios

1.0.6+5 #

Adding reset zoom for iOS

1.0.6+4 #

Fixing default page issue

1.0.6+3 #

Fixing android get page size, scalefactor was missing in the returned value!

1.0.6+2 #

Updating APV version to 1.3.0

1.0.6+1 #

Adding getPageWidth and getPAgeHeight with the scale to controller

1.0.5+5 #

Fixing scale on ios in dual page mode

1.0.5+4 #

Fixing scale on ios in dual page mode

1.0.5+3 #

Adding LICENSE

1.0.5+2 #

Fixing typo

1.0.5+1 #

Adding fitPolicy selector and possility to get the actual zoom

1.0.4+1 #

Adding setPageWithAnimation and resetZoom to the controller

1.0.3+2 #

Fixing vertical scroll on iOS

1.0.3+1 #

Updating with apv version 1.2.0 Adding backgroundColor support Adding dualPageMode support on IOS

1.0.2+9 #

Updating with apv version 1.1.0

1.0.2+8 #

Updating with apv version 1.0.12

1.0.2+7 #

Updating apv version to 1.0.9

1.0.2+6 #

Updating README

1.0.2+5 #

Added dualpage mode based on the orientation of the device

1.0.1+4 #

Updating the README file

1.0.1+3 #

Adding analisys_options.yaml

1.0.1+2 #

New release fixing the channel id for the invoke method and renaming java and objc files

1.0.0+1 #

First release of the updated plugin flutter_pdfview from endigo Fitpolicy from AndroidPdfView is now set to BOTH and the option fitEachPage has been added. The plugin AndroidPdfView from barteksc is not maintained anymore, so flutter_fullpdfview is now using apv => https://github.com/arnaudelub/apv

example/lib/main.dart

import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_fullpdfview/flutter_fullpdfview.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String pathPDF = "";
  String corruptedPathPDF = "";

  @override
  void initState() {
    super.initState();
    fromAsset('assets/corrupted.pdf', 'corrupted.pdf').then((f) {
      setState(() {
        corruptedPathPDF = f.path;
      });
    });
    fromAsset('assets/demo.pdf', 'demo.pdf').then((f) {
      setState(() {
        pathPDF = f.path;
      });
    });
  }

  Future<File> createFileOfPdfUrl() async {
    // final url =
    // "https://berlin2017.droidcon.cod.newthinking.net/sites/global.droidcon.cod.newthinking.net/files/media/documents/Flutter%20-%2060FPS%20UI%20of%20the%20future%20%20-%20DroidconDE%2017.pdf";
    final url = "https://pdfkit.org/docs/guide.pdf";
    final filename = url.substring(url.lastIndexOf("/") + 1);
    var request = await HttpClient().getUrl(Uri.parse(url));
    var response = await request.close();
    var bytes = await consolidateHttpClientResponseBytes(response);
    String dir = (await getApplicationDocumentsDirectory()).path;
    File file = File('$dir/$filename');
    await file.writeAsBytes(bytes);
    return file;
  }

  Future<File> fromAsset(String asset, String filename) async {
    // To open from assets, you can copy them to the app storage folder, and the access them "locally"
    Completer<File> completer = Completer();

    try {
      var dir = await getApplicationDocumentsDirectory();
      File file = File("${dir.path}/$filename");
      var data = await rootBundle.load(asset);
      var bytes = data.buffer.asUint8List();
      await file.writeAsBytes(bytes, flush: true);
      completer.complete(file);
    } catch (e) {
      throw Exception('Error parsing asset file!');
    }

    return completer.future;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter PDF View',
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(title: const Text('Plugin example app')),
        body: Center(child: Builder(
          builder: (BuildContext context) {
            return Column(
              children: <Widget>[
                RaisedButton(
                    child: Text("Open PDF"),
                    onPressed: () {
                      if (pathPDF != null) {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => PDFScreen(path: pathPDF)),
                        );
                      }
                    }),
                RaisedButton(
                    child: Text("Open Corrupted PDF"),
                    onPressed: () {
                      if (pathPDF != null) {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) =>
                                  PDFScreen(path: corruptedPathPDF)),
                        );
                      }
                    })
              ],
            );
          },
        )),
      ),
    );
  }
}

class PDFScreen extends StatefulWidget {
  final String path;
  PDFScreen({Key key, this.path}) : super(key: key);

  _PDFScreenState createState() => _PDFScreenState();
}

class _PDFScreenState extends State<PDFScreen> {
  int pages = 0;
  bool isReady = false;
  String errorMessage = '';
  GlobalKey pdfKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return OrientationBuilder(
        builder: (BuildContext context, Orientation orientation) {
      if (orientation == Orientation.portrait) {
        final Completer<PDFViewController> _controller =
            Completer<PDFViewController>();
        return Scaffold(
          appBar: AppBar(
            title: Text("Document"),
            actions: <Widget>[
              IconButton(
                icon: Icon(Icons.share),
                onPressed: () {},
              ),
            ],
          ),
          body: Stack(
            children: <Widget>[
              Container(
                color: Colors.black,
                child: PDFView(
                  key: pdfKey,
                  filePath: widget.path,
                  fitEachPage: true,
                  fitPolicy: FitPolicy.BOTH,
                  dualPageMode: false,
                  enableSwipe: true,
                  swipeHorizontal: true,
                  autoSpacing: true,
                  pageFling: true,
                  defaultPage: 8,
                  pageSnap: true,
                  backgroundColor: bgcolors.BLACK,
                  onRender: (_pages) {
                    print("OK RENDERED!!!!!");
                    setState(() {
                      pages = _pages;
                      isReady = true;
                    });
                  },
                  onError: (error) {
                    setState(() {
                      errorMessage = error.toString();
                    });
                    print(error.toString());
                  },
                  onPageError: (page, error) {
                    setState(() {
                      errorMessage = '$page: ${error.toString()}';
                    });
                    print('$page: ${error.toString()}');
                  },
                  onViewCreated: (PDFViewController pdfViewController) {
                    _controller.complete(pdfViewController);
                  },
                  onPageChanged: (int page, int total) {
                    print('page change: $page/$total');
                  },
                ),
              ),
              errorMessage.isEmpty
                  ? !isReady
                      ? Center(
                          child: CircularProgressIndicator(),
                        )
                      : Container()
                  : Center(child: Text(errorMessage))
            ],
          ),
          floatingActionButton: FutureBuilder<PDFViewController>(
            future: _controller.future,
            builder: (context, AsyncSnapshot<PDFViewController> snapshot) {
              if (snapshot.hasData) {
                return FloatingActionButton.extended(
                  label: Text("Go to ${pages ~/ 2}"),
                  onPressed: () async {
                    print(await snapshot.data.getZoom());
                    print(await snapshot.data.getPageWidth(1));
                    print(await snapshot.data.getPageHeight(1));
                    //await snapshot.data.setPage(pages ~/ 2);
                    await snapshot.data.resetZoom(1);
                    //print(await snapshot.data.getScreenWidth());
                  },
                );
              }

              return Container();
            },
          ),
        );
      } else {
        final Completer<PDFViewController> _controller =
            Completer<PDFViewController>();
        return PDFView(
          filePath: widget.path,
          fitEachPage: false,
          dualPageMode: true,
          enableSwipe: true,
          swipeHorizontal: true,
          autoSpacing: false,
          pageFling: true,
          defaultPage: 0,
          pageSnap: false,
          backgroundColor: bgcolors.BLACK,
          onRender: (_pages) {
            print("OK RENDERED!!!!!");
            setState(() {
              pages = _pages;
              isReady = true;
            });
          },
          onError: (error) {
            setState(() {
              errorMessage = error.toString();
            });
            print(error.toString());
          },
          onPageError: (page, error) {
            setState(() {
              errorMessage = '$page: ${error.toString()}';
            });
            print('$page: ${error.toString()}');
          },
          onViewCreated: (PDFViewController pdfViewController) {
            _controller.complete(pdfViewController);
          },
          onPageChanged: (int page, int total) {
            print('page change: $page/$total');
          },
        );
      }
    });
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flutter_fullpdfview: ^1.0.8+1

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:flutter_fullpdfview/flutter_fullpdfview.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
72
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
86
Learn more about scoring.

We analyzed this package on Apr 1, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.11 1.14.12
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test