Flutter PDF阅读插件uc_pdfview的使用

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的官方文档。

回到顶部