Flutter PDF缓存查看插件flutter_cached_pdfview的使用

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

Flutter PDF缓存查看插件flutter_cached_pdfview的使用

简介

flutter_cached_pdfview 是一个用于在Flutter应用程序中显示PDF文档的插件,支持从路径、资源或URL加载PDF文件,并且可以对URL来源的PDF进行缓存。它具有跨平台特性(iOS和Android),并且即将支持Web端。

插件特性

  • 支持从本地路径、资源文件或网络链接加载PDF。
  • 支持水平或垂直拖动和缩放。
  • 双击放大功能。
  • 支持加密PDF文件。
  • 可以跳转到指定页码。
  • 提供回调函数处理渲染完成、页面切换等事件。

平台支持

  • Android (>= API 20)
  • iOS (>= 11.0)

安装配置

添加依赖

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

dependencies:
  flutter_cached_pdfview: latest_version

然后执行flutter pub get来安装最新版本的包。

iOS配置

对于iOS项目,需要做以下设置:

  1. 在项目的Info.plist文件中添加键值对:<key>io.flutter.embedded_views_preview</key><true/>
  2. 修改Podfile文件中的平台版本为platform :ios, '11.0'

使用示例

下面是一个完整的Demo代码,展示了如何从不同源加载PDF并实现基本交互:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_cached_pdfview/flutter_cached_pdfview.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
        home: MyHomePage(),
        debugShowCheckedModeBanner: false,
      );
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('flutter_cached_pdfview Demo'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          TextButton(
            onPressed: () => Navigator.push(
              context,
              MaterialPageRoute<dynamic>(
                builder: (_) => const PDFViewerFromUrl(
                  url:
                      'https://ontheline.trincoll.edu/images/bookdown/sample-local-pdf.pdf',
                ),
              ),
            ),
            child: const Text('PDF From Url'),
          ),
          TextButton(
            onPressed: () => Navigator.push(
              context,
              MaterialPageRoute<dynamic>(
                builder: (_) => const PDFViewerCachedFromUrl(
                  url:
                      'https://ontheline.trincoll.edu/images/bookdown/sample-local-pdf.pdf',
                ),
              ),
            ),
            child: const Text('Cashed PDF From Url'),
          ),
          TextButton(
            onPressed: () => Navigator.push(
              context,
              MaterialPageRoute<dynamic>(
                builder: (_) => PDFViewerFromAsset(
                  pdfAssetPath: 'assets/pdf/file-example.pdf',
                ),
              ),
            ),
            child: const Text('PDF From Asset'),
          ),
        ],
      ),
    );
  }
}

// 加载来自URL的PDF
class PDFViewerFromUrl extends StatelessWidget {
  const PDFViewerFromUrl({Key? key, required this.url}) : super(key: key);
  final String url;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('PDF From Url'),
      ),
      body: const PDF().fromUrl(
        url,
        placeholder: (double progress) => Center(child: Text('$progress %')),
        errorWidget: (dynamic error) => Center(child: Text(error.toString())),
      ),
    );
  }
}

// 缓存来自URL的PDF
class PDFViewerCachedFromUrl extends StatelessWidget {
  const PDFViewerCachedFromUrl({Key? key, required this.url})
      : super(key: key);
  final String url;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Cached PDF From Url'),
      ),
      body: const PDF().cachedFromUrl(
        url,
        placeholder: (double progress) => Center(child: Text('$progress %')),
        errorWidget: (dynamic error) => Center(child: Text(error.toString())),
      ),
    );
  }
}

// 加载来自Assets的PDF
class PDFViewerFromAsset extends StatelessWidget {
  PDFViewerFromAsset({Key? key, required this.pdfAssetPath}) : super(key: key);
  final String pdfAssetPath;
  final Completer<PDFViewController> _pdfViewController = Completer<PDFViewController>();
  final StreamController<String> _pageCountController = StreamController<String>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('PDF From Asset'),
        actions: <Widget>[
          StreamBuilder<String>(
              stream: _pageCountController.stream,
              builder: (_, AsyncSnapshot<String> snapshot) {
                if (snapshot.hasData) {
                  return Center(
                    child: Container(
                      padding: const EdgeInsets.all(16),
                      decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        color: Colors.blue[900],
                      ),
                      child: Text(snapshot.data!),
                    ),
                  );
                }
                return const SizedBox();
              }),
        ],
      ),
      body: PDF(
        enableSwipe: true,
        swipeHorizontal: true,
        autoSpacing: false,
        pageFling: false,
        backgroundColor: Colors.grey,
        onPageChanged: (int? current, int? total) =>
            _pageCountController.add('${current! + 1} - $total'),
        onViewCreated: (PDFViewController pdfViewController) async {
          _pdfViewController.complete(pdfViewController);
          final int currentPage = await pdfViewController.getCurrentPage() ?? 0;
          final int? pageCount = await pdfViewController.getPageCount();
          _pageCountController.add('${currentPage + 1} - $pageCount');
        },
      ).fromAsset(
        pdfAssetPath,
        errorWidget: (dynamic error) => Center(child: Text(error.toString())),
      ),
      floatingActionButton: FutureBuilder<PDFViewController>(
        future: _pdfViewController.future,
        builder: (_, AsyncSnapshot<PDFViewController> snapshot) {
          if (snapshot.hasData && snapshot.data != null) {
            return Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                FloatingActionButton(
                  heroTag: '-',
                  child: const Text('-'),
                  onPressed: () async {
                    final PDFViewController pdfController = snapshot.data!;
                    final int currentPage =
                        (await pdfController.getCurrentPage())! - 1;
                    if (currentPage >= 0) {
                      await pdfController.setPage(currentPage);
                    }
                  },
                ),
                FloatingActionButton(
                  heroTag: '+',
                  child: const Text('+'),
                  onPressed: () async {
                    final PDFViewController pdfController = snapshot.data!;
                    final int currentPage =
                        (await pdfController.getCurrentPage())! + 1;
                    final int numberOfPages =
                        await pdfController.getPageCount() ?? 0;
                    if (numberOfPages > currentPage) {
                      await pdfController.setPage(currentPage);
                    }
                  },
                ),
              ],
            );
          }
          return const SizedBox();
        },
      ),
    );
  }
}

通过以上代码,您可以轻松地将PDF集成到您的Flutter应用中,并根据需要选择不同的加载方式。希望这能帮助您更好地理解和使用flutter_cached_pdfview插件!


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

1 回复

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


当然,以下是如何在Flutter项目中使用flutter_cached_pdfview插件来缓存和查看PDF文件的示例代码。

首先,确保你已经在pubspec.yaml文件中添加了flutter_cached_pdfview依赖:

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

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

接下来,在你的Flutter项目中,你可以按照以下步骤使用flutter_cached_pdfview插件:

  1. 导入必要的包
import 'package:flutter/material.dart';
import 'package:flutter_cached_pdfview/flutter_cached_pdfview.dart';
import 'package:path_provider/path_provider.dart';
  1. 创建一个函数来下载并缓存PDF文件
Future<File> downloadAndCachePdf(String url) async {
  final directory = await getApplicationDocumentsDirectory();
  final filePath = "${directory.path}/${url.split('/').last}";
  final file = File(filePath);

  if (!await file.exists()) {
    final response = await http.get(Uri.parse(url));
    await file.writeAsBytes(response.bodyBytes);
  }

  return file;
}
  1. 在你的Widget中使用CachedPdfView来显示PDF
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Cached PDF View Example'),
        ),
        body: Center(
          child: PdfViewerScreen(),
        ),
      ),
    );
  }
}

class PdfViewerScreen extends StatefulWidget {
  @override
  _PdfViewerScreenState createState() => _PdfViewerScreenState();
}

class _PdfViewerScreenState extends State<PdfViewerScreen> {
  late Future<File> pdfFileFuture;

  @override
  void initState() {
    super.initState();
    pdfFileFuture = downloadAndCachePdf('https://example.com/sample.pdf'); // 替换为你的PDF URL
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<File>(
      future: pdfFileFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.hasError) {
            return Text('Failed to load PDF');
          } else {
            final file = snapshot.data!;
            return CachedPdfView(
              filePath: file.path,
              password: null, // 如果PDF有密码,可以在这里提供
              onError: (error) {
                // 处理加载PDF时发生的错误
                print('Error loading PDF: $error');
              },
              onPageChanged: (page, pageCount) {
                // 页面改变时的回调
                print('Page changed: $page/$pageCount');
              },
              onLoad: () {
                // PDF加载完成时的回调
                print('PDF loaded');
              },
            );
          }
        } else {
          return CircularProgressIndicator();
        }
      },
    );
  }
}

在这个示例中,我们:

  1. 使用getApplicationDocumentsDirectory来获取应用的文档目录,以便缓存PDF文件。
  2. 使用http.get来下载PDF文件,并将其保存到应用的文档目录中。
  3. 使用FutureBuilder来异步加载PDF文件,并在加载完成后使用CachedPdfView来显示PDF。

请确保在实际项目中处理错误和异常情况,并根据需要调整代码。

回到顶部