Integrate WebViewer into a Flutter App to Enable Cross-Platform Document Viewing

This sample demonstrates document viewing and targets Android and iOS mobile devices.

Apryse's WebViewer is integrated into a Flutter web project using Dart programming language to create the viewer. For more information, see this guide.

WebViewer provides a slick out-of-the-box responsive UI that enables you to view, annotate and manipulate PDFs and other document types inside any web project.

Click the button below to view the full project in GitHub.

1import 'package:flutter/material.dart';
2
3import 'dart:ui_web' as ui;
4import 'dart:html' as html;
5
6void main() {
7 runApp(MyApp());
8}
9
10class MyApp extends StatelessWidget {
11 // This widget is the root of your application.
12 @override
13 Widget build(BuildContext context) {
14 return MaterialApp(
15 title: 'Apryse Flutter Demo',
16 theme: ThemeData(
17 // This is the theme of your application.
18 //
19 // Try running your application with "flutter run". You'll see the
20 // application has a blue toolbar. Then, without quitting the app, try
21 // changing the primarySwatch below to Colors.green and then invoke
22 // "hot reload" (press "r" in the console where you ran "flutter run",
23 // or simply save your changes to "hot reload" in a Flutter IDE).
24 // Notice that the counter didn't reset back to zero; the application
25 // is not restarted.
26 primarySwatch: Colors.blue,
27 // This makes the visual density adapt to the platform that you run
28 // the app on. For desktop platforms, the controls will be smaller and
29 // closer together (more dense) than on mobile platforms.
30 visualDensity: VisualDensity.adaptivePlatformDensity,
31 ),
32 home: MyHomePage(title: 'Apryse WebViewer for Flutter'),
33 );
34 }
35}
36
37class MyHomePage extends StatefulWidget {
38 MyHomePage({wkey,required this.title}) : super(key: wkey);
39
40 // This widget is the home page of your application. It is stateful, meaning
41 // that it has a State object (defined below) that contains fields that affect
42 // how it looks.
43
44 // This class is the configuration for the state. It holds the values (in this
45 // case the title) provided by the parent (in this case the App widget) and
46 // used by the build method of the State. Fields in a Widget subclass are
47 // always marked "final".
48
49 final String title;
50
51 @override
52 _MyHomePageState createState() => _MyHomePageState();
53}
54
55String viewID = "webviewer-id";
56
57class _MyHomePageState extends State<MyHomePage> {
58
59 @override
60 void initState() {
61 super.initState();
62
63 html.DivElement _element = html.DivElement();
64 _element
65 ..id = 'canvas'
66 ..style.height = '100%'
67 ..style.width = '100%'
68 ..append(html.ScriptElement()
69 ..text = """
70 // Defines a ShadowRoot within DOM, and is set to 'Open'
71 // Reference: https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot
72 const shadowHost = document.querySelector("flt-platform-view").querySelector("#canvas");
73 const shadowRoot = shadowHost.attachShadow({ mode: 'open' });
74
75 WebViewer({
76 path: 'WebViewer/lib',
77 initialDoc: 'https://pdftron.s3.amazonaws.com/downloads/pl/demo.pdf'
78 }, shadowRoot).then((instance) => {
79 // call apis here
80 });
81 """);
82
83 // ignore: undefined_prefixed_name
84 ui.platformViewRegistry
85 .registerViewFactory(viewID, (int viewId) => _element);
86 }
87
88 @override
89 Widget build(BuildContext context) {
90 // This method is rerun every time setState is called
91 //
92 // The Flutter framework has been optimized to make rerunning build methods
93 // fast, so that you can just rebuild anything that needs updating rather
94 // than having to individually change instances of widgets.
95 return Scaffold(
96 appBar: AppBar(
97 // Here we take the value from the MyHomePage object that was created by
98 // the App.build method, and use it to set our appbar title.
99 title: Text(widget.title),
100 ),
101 body: FractionallySizedBox(
102 widthFactor: 1,
103 heightFactor: 1,
104 child: Container(
105 alignment: Alignment.center,
106 child: HtmlElementView(
107 viewType: viewID,
108 ),
109 ),
110 ), // This trailing comma makes auto-formatting nicer for build methods.
111 );
112 }
113}
114

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales