求助:使用syncfusion_flutter_pdf实现PDF高亮标注的存储与读取
解决Syncfusion Flutter PDF高亮标注的持久化问题
要实现高亮标注的存储与读取,核心思路是将标注的关键信息序列化后保存到本地,下次打开PDF时再反序列化并恢复标注。以下是具体实现步骤和完整代码:
1. 添加依赖
在pubspec.yaml中添加本地存储依赖:
dependencies: flutter: sdk: flutter syncfusion_flutter_pdfviewer: ^latest_version shared_preferences: ^2.2.2
2. 定义可序列化的标注模型
创建SavedHighlight类存储高亮标注的关键属性(Syncfusion原生Annotation无法直接序列化):
class SavedHighlight { final int pageNumber; final List<PdfTextSpan> textSpans; final int colorValue; SavedHighlight({ required this.pageNumber, required this.textSpans, required this.colorValue, }); // 转换为JSON格式 Map<String, dynamic> toJson() { return { 'pageNumber': pageNumber, 'textSpans': textSpans.map((span) => { 'startIndex': span.startIndex, 'endIndex': span.endIndex, }).toList(), 'colorValue': colorValue, }; } // 从JSON解析为对象 factory SavedHighlight.fromJson(Map<String, dynamic> json) { final textSpans = (json['textSpans'] as List) .map((e) => PdfTextSpan( startIndex: e['startIndex'], endIndex: e['endIndex'], )) .toList(); return SavedHighlight( pageNumber: json['pageNumber'], textSpans: textSpans, colorValue: json['colorValue'], ); } }
3. 实现保存与加载逻辑
修改原页面代码,加入存储和读取标注的方法:
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'dart:developer' as dev; class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey(); late PdfViewerController _controller; late SharedPreferences _prefs; final String _annotationKey = 'pdf_highlights'; // 存储标注的键名 @override void initState() { super.initState(); _controller = PdfViewerController(); _initPrefsAndLoadAnnotations(); } // 初始化本地存储并加载标注 Future<void> _initPrefsAndLoadAnnotations() async { _prefs = await SharedPreferences.getInstance(); await _loadAnnotations(); } // 加载保存的高亮标注 Future<void> _loadAnnotations() async { final String? savedJson = _prefs.getString(_annotationKey); if (savedJson == null) return; final List<dynamic> jsonList = jsonDecode(savedJson); final List<SavedHighlight> savedHighlights = jsonList .map((json) => SavedHighlight.fromJson(json)) .toList(); // 将保存的高亮转换为Syncfusion标注并添加到控制器 for (var highlight in savedHighlights) { final textMarkupAnnotation = TextMarkupAnnotation( textMarkupType: TextMarkupType.highlight, color: Color(highlight.colorValue), textSpans: highlight.textSpans, pageNumber: highlight.pageNumber, ); _controller.addAnnotation(textMarkupAnnotation); } } // 保存当前所有高亮标注 Future<void> _saveAnnotations() async { // 只筛选高亮类型的标注 final List<Annotation> annotations = _controller.getAnnotations() .where((anno) => anno is TextMarkupAnnotation && (anno as TextMarkupAnnotation).textMarkupType == TextMarkupType.highlight) .toList(); // 转换为可序列化的SavedHighlight列表 final List<SavedHighlight> savedHighlights = annotations.map((anno) { final highlight = anno as TextMarkupAnnotation; return SavedHighlight( pageNumber: highlight.pageNumber, textSpans: highlight.textSpans, colorValue: highlight.color.value, ); }).toList(); // 转成JSON字符串保存到本地 final String jsonStr = jsonEncode(savedHighlights); await _prefs.setString(_annotationKey, jsonStr); dev.log('标注已保存'); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Syncfusion Flutter PDF Viewer'), actions: <Widget>[ IconButton( icon: const Icon( Icons.bookmark, color: Colors.white, semanticLabel: 'Bookmark', ), onPressed: () { _pdfViewerKey.currentState?.openBookmarkView(); }, ), // 手动保存按钮(可选,配合自动保存使用) IconButton( icon: const Icon(Icons.save, color: Colors.white), onPressed: _saveAnnotations, ), ], ), body: SfPdfViewer.asset( 'assets/name.pdf', controller: _controller, onAnnotationAdded: (Annotation annotation) { if (annotation is TextMarkupAnnotation && annotation.textMarkupType == TextMarkupType.highlight) { annotation.color = Colors.yellow; _saveAnnotations(); // 添加标注后自动保存 } }, onAnnotationEdited: (Annotation annotation) { if (annotation is TextMarkupAnnotation && annotation.textMarkupType == TextMarkupType.highlight) { annotation.color = Colors.blue; _saveAnnotations(); // 编辑标注后自动保存 } }, onAnnotationRemoved: (Annotation annotation) { if (annotation is TextMarkupAnnotation && annotation.textMarkupType == TextMarkupType.highlight) { _saveAnnotations(); // 删除标注后自动保存 } }, key: _pdfViewerKey, ), ); } }
关键说明
- 序列化逻辑:提取
TextMarkupAnnotation的页码、文本范围、颜色值核心属性,转换成可JSON序列化的格式存储。 - 自动持久化:在标注添加、编辑、删除时自动触发保存,确保标注状态实时同步到本地;也可保留手动保存按钮作为补充。
- 标注恢复:页面初始化时读取本地存储的标注,转换为Syncfusion原生标注对象并添加到控制器,实现打开PDF时自动恢复高亮。
- 类型过滤:仅处理
TextMarkupType.highlight类型的标注,避免混入下划线、删除线等其他注释类型。
内容的提问来源于stack exchange,提问作者coder lover
相关产品推荐
相关产品推荐

