Flutter PDF阅读插件uc_pdfview的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter PDF阅读插件uc_pdfview的使用

uc_pdfview 是一个基于 Flutter 的 PDF 查看插件,支持 iOS 和 Android 平台。它提供了丰富的功能和选项,帮助开发者轻松集成 PDF 查看功能到 Flutter 应用中。以下是关于如何使用 uc_pdfview 插件的详细说明,并附带一个完整的示例代码。

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 uc_pdfview 依赖:

dependencies:
  uc_pdfview: ^0.0.1

然后,通过命令行安装依赖:

flutter packages get

2. 设置

iOS 设置

对于 iOS,需要在 Info.plist 文件中添加以下键值对,以启用嵌入式视图预览:

<key>io.flutter.embedded_views_preview</key>
<true/>

3. 导入库

在 Dart 代码中导入 uc_pdfview

import 'package:uc_pdfview/uc_pdfview.dart';

4. 配置选项

UCPDFView 提供了多个配置选项,用于自定义 PDF 查看器的行为。以下是一些常用的选项及其默认值:

名称 Android iOS 默认值
defaultPage 0
onViewCreated null
onRender null
onPageChanged null
onError null
onPageError null
onLinkHandle null
gestureRecognizers null
filePath
pdfData
fitPolicy FitPolicy.WIDTH
enableSwipe true
swipeHorizontal false
password null
nightMode false
autoSpacing true
pageFling true
pageSnap true
preventLinkNavigation false

5. 控制器选项

PDFViewController 提供了一些方法来控制 PDF 查看器的行为:

名称 描述 参数 返回值
getPageCount 获取总页数 - Future<int>
getCurrentPage 获取当前页数 - Future<int>
setPage 跳转到指定页数 int page Future<bool>

6. 示例代码

以下是一个完整的示例代码,展示了如何使用 uc_pdfview 插件来查看本地和远程 PDF 文件。

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:uc_pdfview/uc_pdfview.dart';

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

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

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

  @override
  void initState() {
    super.initState();
    // 加载本地 PDF 文件
    fromAsset('assets/corrupted.pdf', 'corrupted.pdf').then((f) {
      setState(() {
        corruptedPathPDF = f.path;
      });
    });
    fromAsset('assets/demo-link.pdf', 'demo.pdf').then((f) {
      setState(() {
        pathPDF = f.path;
      });
    });
    fromAsset('assets/demo-landscape.pdf', 'landscape.pdf').then((f) {
      setState(() {
        landscapePathPdf = f.path;
      });
    });

    // 下载远程 PDF 文件
    createFileOfPdfUrl().then((f) {
      setState(() {
        remotePDFpath = f.path;
      });
    });
  }

  // 从网络下载 PDF 文件并保存到本地
  Future<File> createFileOfPdfUrl() async {
    Completer<File> completer = Completer();
    print("开始从互联网下载文件!");
    try {
      final url = "http://www.pdf995.com/samples/pdf.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);
      var dir = await getApplicationDocumentsDirectory();
      print("下载文件路径: ${dir.path}/$filename");
      File file = File("${dir.path}/$filename");

      await file.writeAsBytes(bytes, flush: true);
      completer.complete(file);
    } catch (e) {
      throw Exception('解析资产文件时出错!');
    }

    return completer.future;
  }

  // 从 assets 中加载 PDF 文件
  Future<File> fromAsset(String asset, String filename) async {
    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('解析资产文件时出错!');
    }

    return completer.future;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter PDF View',
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(title: const Text('PDF 查看器示例')),
        body: Center(
          child: Column(
            children: <Widget>[
              TextButton(
                child: Text("打开 PDF"),
                onPressed: () {
                  if (pathPDF.isNotEmpty) {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => PDFScreen(path: pathPDF),
                      ),
                    );
                  }
                },
              ),
              TextButton(
                child: Text("打开横向 PDF"),
                onPressed: () {
                  if (landscapePathPdf.isNotEmpty) {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) =>
                            PDFScreen(path: landscapePathPdf),
                      ),
                    );
                  }
                },
              ),
              TextButton(
                child: Text("打开远程 PDF"),
                onPressed: () {
                  if (remotePDFpath.isNotEmpty) {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) =>
                            PDFScreen(path: remotePDFpath),
                      ),
                    );
                  }
                },
              ),
              TextButton(
                child: Text("打开损坏的 PDF"),
                onPressed: () {
                  if (corruptedPathPDF.isNotEmpty) {
                    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> with WidgetsBindingObserver {
  final Completer<PDFViewController> _controller = Completer<PDFViewController>();
  int? pages = 0;
  int? currentPage = 0;
  bool isReady = false;
  String errorMessage = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("文档"),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.share),
            onPressed: () {},
          ),
        ],
      ),
      body: Stack(
        children: <Widget>[
          UCPDFView(
            filePath: widget.path,
            enableSwipe: true,
            swipeHorizontal: true,
            autoSpacing: false,
            pageFling: true,
            pageSnap: true,
            defaultPage: currentPage!,
            fitPolicy: FitPolicy.BOTH,
            preventLinkNavigation: false, // 如果设置为 true,则链接由 Flutter 处理
            onRender: (_pages) {
              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);
            },
            onLinkHandler: (String? uri) {
              print('跳转到 URI: $uri');
            },
            onPageChanged: (int? page, int? total) {
              print('页面变化: $page/$total');
              setState(() {
                currentPage = page;
              });
            },
          ),
          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("跳转到 ${pages! ~/ 2}"),
              onPressed: () async {
                await snapshot.data!.setPage(pages! ~/ 2);
              },
            );
          }

          return Container();
        },
      ),
    );
  }
}

7. 生产环境使用

如果你使用 ProGuard,确保包含以下行:

-keep class com.shockwave.**

更多关于Flutter PDF阅读插件uc_pdfview的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter PDF阅读插件uc_pdfview的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用uc_pdfview插件来展示PDF文件的示例代码。uc_pdfview是一个流行的Flutter插件,用于在应用中嵌入和显示PDF文档。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加uc_pdfview的依赖:

dependencies:
  flutter:
    sdk: flutter
  uc_pdfview: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

2. 导入插件

在你的Dart文件中导入uc_pdfview插件:

import 'package:flutter/material.dart';
import 'package:uc_pdfview/uc_pdfview.dart';

3. 使用PDFView组件

下面是一个完整的示例,展示了如何使用PDFView组件来显示PDF文件:

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter PDF Reader',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: PDFViewerScreen(),
    );
  }
}

class PDFViewerScreen extends StatefulWidget {
  @override
  _PDFViewerScreenState createState() => _PDFViewerScreenState();
}

class _PDFViewerScreenState extends State<PDFViewerScreen> {
  @override
  Widget build(BuildContext context) {
    // 本地PDF文件路径(可以是从网络下载或本地资源)
    final String pdfUrl = 'assets/sample.pdf'; // 确保在pubspec.yaml中声明了assets

    return Scaffold(
      appBar: AppBar(
        title: Text('PDF Viewer'),
      ),
      body: Center(
        child: PDFView(
          filePath: pdfUrl,
          password: null, // 如果PDF文件有密码,可以在这里提供
          autoSpacing: false,
          pageFling: true,
          swipeHorizontal: true,
          pageSnap: true,
          nightMode: false,
          autoScroll: false,
          defaultPage: 0,
          onError: (error) {
            // 处理加载PDF文件时的错误
            print('Error loading PDF: $error');
          },
          onRender: (_) {
            // PDF文件渲染完成时的回调
            print('PDF rendered');
          },
          onPageChanged: (page) {
            // 页面改变时的回调
            print('Page changed to: $page');
          },
          onProgress: (progress) {
            // 加载进度回调
            print('Loading progress: $progress');
          },
        ),
      ),
    );
  }
}

4. 在pubspec.yaml中声明assets

如果你的PDF文件是放在assets文件夹中的,你需要在pubspec.yaml文件中声明它:

flutter:
  assets:
    - assets/sample.pdf

注意事项

  • 确保你的PDF文件路径是正确的。如果是从网络加载,可以直接使用URL。
  • uc_pdfview插件依赖于原生组件,因此需要在iOS和Android平台上进行一些配置,但大多数情况下,插件会自动处理这些配置。
  • 根据你的需求,你可以调整PDFView组件的各种参数,如是否启用夜间模式、是否自动滚动等。

这样,你就可以在Flutter应用中展示PDF文件了。如果有任何问题或需要进一步的自定义,请参考uc_pdfview的官方文档。

回到顶部