Flutter PDF View 在鸿蒙平台的使用指南
flutter_pdfview_ohos是专为HarmonyOS适配的Flutter PDF查看插件,支持本地/远程文件加载、页面导航、缩放等功能。通过Git引入依赖后,开发者可使用PDFView组件展示PDF文档,并通过控制器实现页面跳转等操作。该插件在HarmonyOS上暂不支持二进制数据加载和水平滑动翻页功能。
1. 插件介绍
flutter_pdfview_ohos 是一个基于 flutter_pdfview@1.3.3 开发的 HarmonyOS 适配版本,用于在 Flutter 应用中展示 PDF 文件。该插件提供了丰富的 PDF 浏览功能,包括页面导航、缩放、链接处理等,帮助开发者轻松实现 PDF 文档的查看功能。

核心功能
- 支持本地和远程 PDF 文件加载
- 提供页面导航控制
- 支持缩放和页面适应策略
- 链接处理和自定义链接导航
- 页面渲染和错误处理回调
2. 安装与配置
2.1 添加依赖
由于这是一个自定义修改的 HarmonyOS 适配版本,需要通过 Git 形式引入。在项目的 pubspec.yaml 文件中添加以下依赖:
dependencies:
flutter_pdfview_ohos:
git:
url: "https://atomgit.com/openharmony-sig/fluttertpc_flutter_pdfview.git"
path: "ohos"
ref: master
path_provider:
git:
url: "https://atomgit.com/openharmony-sig/fluttertpc_path_provider.git"
path: "path_provider"
然后执行以下命令获取依赖:
flutter pub get
3. API 使用
3.1 核心组件
PDFView 组件
PDFView 是主要的 PDF 浏览组件,提供了丰富的属性配置:
| 属性 | 类型 | 描述 | HarmonyOS 支持 |
|---|---|---|---|
| filePath | String? | PDF 文件路径 | yes |
| pdfData | Uint8List? | PDF 文件二进制数据 | no |
| enableSwipe | bool | 是否允许滑动翻页 | yes |
| swipeHorizontal | bool | 是否允许水平滑动翻页 | no |
| defaultPage | int | 默认显示页码 | yes |
| fitPolicy | FitPolicy | 页面适应策略 | yes |
| onViewCreated | PDFViewCreatedCallback? | 视图创建回调 | yes |
| onRender | RenderCallback? | 渲染完成回调 | yes |
| onPageChanged | PageChangedCallback? | 页面变化回调 | yes |
| onError | ErrorCallback? | 错误回调 | yes |
PDFViewController 控制器
通过 onViewCreated 回调获取控制器,用于操作 PDF 视图:
| 方法 | 返回类型 | 描述 |
|---|---|---|
| getPageCount() | Future<int?> | 获取总页数 |
| getCurrentPage() | Future<int?> | 获取当前页码 |
| setPage(int page) | Future<bool?> | 设置当前页码 |
3.2 基本使用
加载本地 PDF 文件
import 'package:flutter_pdfview_ohos/flutter_pdfview_ohos.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/services.dart';
import 'dart:io';
// 从 assets 复制文件到本地
Future<File> fromAsset(String asset, String filename) async {
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);
return file;
}
// 使用 PDFView 组件
class PDFScreen extends StatefulWidget {
final String? path;
PDFScreen({Key? key, this.path}) : super(key: key);
_PDFScreenState createState() => _PDFScreenState();
}
class _PDFScreenState extends State<PDFScreen> {
final Completer<PDFViewController> _controller = Completer<PDFViewController>();
int? pages = 0;
int? currentPage = 0;
bool isReady = false;
String errorMessage = '';
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("PDF Viewer")),
body: Stack(
children: <Widget>[
PDFView(
filePath: widget.path,
enableSwipe: true,
fitPolicy: FitPolicy.BOTH,
defaultPage: currentPage!,
onRender: (_pages) {
setState(() {
pages = _pages;
isReady = true;
});
},
onError: (error) {
setState(() {
errorMessage = error.toString();
});
},
onPageChanged: (int? page, int? total) {
print('page change: $page/$total');
setState(() {
currentPage = page;
});
},
onViewCreated: (PDFViewController pdfViewController) {
_controller.complete(pdfViewController);
},
),
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("Go to Last Page"),
onPressed: () async {
await snapshot.data!.setPage(pages! - 1);
},
);
}
return Container();
},
),
);
}
}
加载远程 PDF 文件
Future<File> createFileOfPdfUrl() async {
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();
File file = File("${dir.path}/$filename");
await file.writeAsBytes(bytes, flush: true);
return file;
}
// 使用示例
createFileOfPdfUrl().then((file) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PDFScreen(path: file.path),
),
);
});
4. 约束与限制
在 HarmonyOS 平台上使用此插件时,需要注意以下限制:
- PDF 二进制数据加载:
pdfData属性在 HarmonyOS 上无效,只能通过filePath加载文件 - 水平滑动翻页:
swipeHorizontal设置无效,仅支持垂直滑动 - 夜间模式:
nightMode设置无效 - 自动间距:
autoSpacing设置无效 - 翻页效果:
pageFling和pageSnap设置无效
5. 完整示例
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_pdfview_ohos/flutter_pdfview_ohos.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String pathPDF = "";
String remotePDFpath = "";
void initState() {
super.initState();
fromAsset('assets/demo.pdf', 'demo.pdf').then((f) {
setState(() {
pathPDF = f.path;
});
});
createFileOfPdfUrl().then((f) {
setState(() {
remotePDFpath = f.path;
});
});
}
Future<File> createFileOfPdfUrl() async {
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();
File file = File("${dir.path}/$filename");
await file.writeAsBytes(bytes, flush: true);
return file;
}
Future<File> fromAsset(String asset, String filename) async {
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);
return file;
}
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter PDF View Example',
home: Scaffold(
appBar: AppBar(title: Text('PDF View Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
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 (remotePDFpath.isNotEmpty) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PDFScreen(path: remotePDFpath),
),
);
}
},
),
],
),
),
),
);
}
}
class PDFScreen extends StatefulWidget {
final String? path;
PDFScreen({Key? key, this.path}) : super(key: key);
_PDFScreenState createState() => _PDFScreenState();
}
class _PDFScreenState extends State<PDFScreen> {
final Completer<PDFViewController> _controller = Completer<PDFViewController>();
int? pages = 0;
int? currentPage = 0;
bool isReady = false;
String errorMessage = '';
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("PDF Document"),
),
body: Stack(
children: <Widget>[
PDFView(
filePath: widget.path,
enableSwipe: true,
autoSpacing: false,
pageFling: true,
defaultPage: currentPage!,
fitPolicy: FitPolicy.BOTH,
preventLinkNavigation: false,
onRender: (_pages) {
setState(() {
pages = _pages;
isReady = true;
});
},
onError: (error) {
setState(() {
errorMessage = error.toString();
});
},
onPageError: (page, error) {
setState(() {
errorMessage = '$page: ${error.toString()}';
});
},
onViewCreated: (PDFViewController pdfViewController) {
_controller.complete(pdfViewController);
},
onPageChanged: (int? page, int? total) {
setState(() {
currentPage = page;
});
},
),
errorMessage.isEmpty
? !isReady
? Center(child: CircularProgressIndicator())
: Container()
: Center(child: Text(errorMessage))
],
),
bottomNavigationBar: BottomAppBar(
shape: const CircularNotchedRectangle(),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: Icon(Icons.chevron_left),
onPressed: () {
_controller.future.then((controller) {
controller.setPage(currentPage! - 1);
});
},
),
Text("${currentPage! + 1}/${pages!}"),
IconButton(
icon: Icon(Icons.chevron_right),
onPressed: () {
_controller.future.then((controller) {
controller.setPage(currentPage! + 1);
});
},
),
],
),
),
);
}
}
6. 总结
flutter_pdfview_ohos 是一个功能强大的 PDF 查看插件,为 HarmonyOS 上的 Flutter 应用提供了便捷的 PDF 浏览功能。通过本文的介绍,你可以了解到如何在 HarmonyOS 项目中配置和使用这个插件,实现本地和远程 PDF 文件的加载和查看。
虽然在 HarmonyOS 平台上存在一些功能限制,但核心的 PDF 查看功能都得到了很好的支持。开发者可以根据实际需求,灵活配置和使用这个插件,为用户提供良好的 PDF 阅读体验。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)