Reputation: 377
I want to show a PDF file with the package native_pdf_view (https://pub.dev/packages/native_pdf_view) in my app.
I tried it like this:
class OStundenplan extends StatelessWidget {
final pdfController = PdfController(
document: PdfDocument.openAsset('assets/stundenplan.pdf'),
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Offline Stundenplan'),
),
body: Builder(builder: (BuildContext context) {
return PdfView(controller: _pdfController);
}));
}
}
ostundenplan() {
Navigator.push(
context,
MaterialPageRoute(
Widget pdfView() => PdfView(
controller: pdfController,
);
}
later in the app:
RaisedButton.icon(onPressed: ostundenplan, icon: Icon(Icons.signal_wifi_off), label: Text('Offline Stundenplan'),),
but it doesn't work. Can anyone help me?
EDIT:
When I try it like pradyot1996 says, I get this:
Compiler message:
lib/main.dart:315:37: Error: Type 'PDFReader' not found.
class _PDFReaderState extends State<PDFReader> {
^^^^^^^^^
lib/main.dart:315:7: Error: Type argument 'invalid-type' doesn't conform to the bound 'StatefulWidget' of the type variable 'T' on 'State' in the supertype 'State' of class '_PDFReaderState'.
- 'StatefulWidget' is from 'package:flutter/src/widgets/framework.dart' ('/C:/flutter/packages/flutter/lib/src/widgets/framework.dart').
Try changing type arguments so that they conform to the bounds.
class _PDFReaderState extends State<PDFReader> {
^
/C:/flutter/packages/flutter/lib/src/widgets/framework.dart:1029:22: Context: This is the type variable whose bound isn't conformed to.
abstract class State<T extends StatefulWidget> with Diagnosticable {
^
Compiler message:
lib/main.dart:315:37: Error: Type 'PDFReader' not found.
class _PDFReaderState extends State<PDFReader> {
^^^^^^^^^
lib/main.dart:315:7: Error: Type argument 'invalid-type' doesn't conform to the bound 'StatefulWidget' of the type variable 'T' on 'State' in the supertype 'State' of class '_PDFReaderState'.
- 'StatefulWidget' is from 'package:flutter/src/widgets/framework.dart' ('/C:/flutter/packages/flutter/lib/src/widgets/framework.dart').
Try changing type arguments so that they conform to the bounds.
class _PDFReaderState extends State<PDFReader> {
^
/C:/flutter/packages/flutter/lib/src/widgets/framework.dart:1029:22: Context: This is the type variable whose bound isn't conformed to.
abstract class State<T extends StatefulWidget> with Diagnosticable {
^
Target kernel_snapshot failed: Exception: Errors during snapshot creation: null
build failed.
^^^^^^^^^^
Looks like it didn't find the PDFReader
.
What can I do?
EDIT 2:
btw, this is my navigator:
ostundenplan() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PDFReader()));
}
EDIT 3:
class PDFReader extends StatefulWidget {
static const route_name = 'pdf_reader';
@override
_PDFReaderState createState() => _PDFReaderState();
}
class _PDFReaderState extends State<PDFReader> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Offline Stundenplan'),
),
body: FutureBuilder(
future: PDFDocument.fromAsset('assets/stundenplan.pdf'),
builder: (_, pdfData) {},
),
);
}
}
Upvotes: 0
Views: 2378
Reputation: 56
If you wish to do it with the original library "(https://pub.dev/packages/native_pdf_view)" you can do this:
You need to use a Stateful widget if you want to interact with the PDF. (let say your PDF have more than 1 page)
When you call the PdfView remember to include the document and the controller. (You were missing the asset path in the constructor of PdfView).
PdfView(
controller: _pdfController,
onDocumentLoaded: (document) {
setState(() {
_allPagesCount = document.pagesCount;
});
},
onPageChanged: (page) {
setState(() {
_actualPageNumber = page;
});
},
),
The above code is an extract from the original library example: https://pub.dev/packages/native_pdf_view/example
So your code should look something like this:
ostundenplan() {
Navigator.push(
context,
MaterialPageRoute(
Widget pdfView() => PdfView(
controller: pdfController,
onDocumentLoaded: (document) {
setState(() {
_allPagesCount = document.pagesCount;
});
},
onPageChanged: (page) {
setState(() {
_actualPageNumber = page;
});
},
),
);
}
adding these variables at the top of your class as well:
int _actualPageNumber = _initialPage, _allPagesCount = 0;
This help you without changing your initial library.
Upvotes: 0
Reputation: 1074
Try this package flutter_plugin_pdf_viewer .
This works perfectly fine for me. I had the PDF file saved in firebase storage and open it through the URL.
PDFDocument doc = await PDFDocument.fromURL(LINK);
PDFViewer(document: doc)
EDIT:
Below class shows the implementation. You can even use a StatelessWidget class if you don't need to refresh the state.
class PDFReader extends StatefulWidget {
static const route_name = 'pdf_reader';
@override
_PDFReaderState createState() => _PDFReaderState();
}
class _PDFReaderState extends State<PDFReader> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Document'),
),
body: FutureBuilder(
future: PDFDocument.fromURL('http://www.africau.edu/images/default/sample.pdf'),
builder: (_, pdfData) {
if (pdfData.connectionState == ConnectionState.waiting) {
return CenterCircularProgressBar();
} else if (pdfData.data == null) {
return CenterText('Not able to open PDF file');
} else {
return PDFViewer(document: pdfData.data);
}
},
),
);
}
}
Now you just need to Navigate to PDFReader widget. If you want to pass the PDF data from one screen to another you can also do that instead of hard coding it in the PDFReader screen.
CenterCircularProgressBar() is a custom widget which shows a Circular progress bar in the center of the screen till the PDF is loaded and, CenterText is a custom widget which shows an error if we don't get the data back from the PDFDocument.fromURL. Code is given below.
So in this line
PDFDocument.fromURL('http://www.africau.edu/images/default/sample.pdf')
You can use the fromAsset, fromURL and fromFile methods provide by the PDFDocument to show the PDF. PDFViewer is custom class provided by the package which will handle the PDF view.
class CenterCircularProgressBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const Center(
child: CircularProgressIndicator(),
);
}
}
class CenterText extends StatelessWidget {
final String stringValue;
CenterText(this.stringValue);
@override
Widget build(BuildContext context) {
return Center(
child: Text(
stringValue,
),
);
}
}
Upvotes: 5