Flutter实现从Firebase实时数据库加载PDF并在App内查看
实现Flutter内联PDF查看功能
你已经引入了advance_pdf_viewer包,现在只需要补充PDF文档的加载状态管理和视图展示逻辑,就能在App内直接查看PDF,无需跳转外部浏览器。以下是修改后的完整方案:
修改说明
- 新增专用PDF查看页面,用于展示加载后的PDF内容
- 补充PDF加载流程的状态提示,优化用户体验
- 处理加载失败的异常情况,给出友好提示
完整修改代码
import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_database/ui/firebase_animated_list.dart'; import 'package:flutter/material.dart'; import 'package:my_project/hello/Courses.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:advance_pdf_viewer/advance_pdf_viewer.dart'; class ViewCourses extends StatefulWidget { const ViewCourses({super.key}); @override State<ViewCourses> createState() => _ViewCoursesState(); } class _ViewCoursesState extends State<ViewCourses> { Query dbRef = FirebaseDatabase.instance.ref().child('Students'); DatabaseReference reference = FirebaseDatabase.instance.ref().child('Students'); Widget listItem({required Map student}) { if (!mounted) return Container(); return SingleChildScrollView( child: GestureDetector( onTap: () {}, child: Container( margin: const EdgeInsets.all(10), padding: const EdgeInsets.all(10), height: 300, color: const Color.fromARGB(255, 255, 200, 0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( (student['Course'] ?? "").toString(), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400), ), const SizedBox(height: 5), Text( (student['Title'] ?? "").toString(), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400), ), const SizedBox(height: 5), Text( (student['CreatedBy'] ?? "").toString(), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400), ), Text( (student['file'] ?? "").toString(), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400), ), Row( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.center, children: [ GestureDetector( onTap: () {}, child: Row( children: [ Icon( Icons.edit, color: Theme.of(context).primaryColor, ), ], ), ), const SizedBox(width: 6), GestureDetector( onTap: () { reference.child(student['key']).remove(); }, child: Row( children: [ Icon( Icons.delete, color: Colors.red[700], ), ], ), ), ElevatedButton( onPressed: () async { // 显示加载提示弹窗 showDialog( context: context, barrierDismissible: false, builder: (context) => const Center(child: CircularProgressIndicator()), ); try { // 从URL加载PDF文档 final pdfDoc = await PDFDocument.fromURL(student['file']); // 关闭加载弹窗并跳转到PDF查看页 Navigator.pop(context); Navigator.push( context, MaterialPageRoute( builder: (context) => PDFViewerPage(pdfDocument: pdfDoc), ), ); } catch (e) { // 加载失败时关闭弹窗并提示错误 Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('PDF加载失败: ${e.toString()}')), ); } }, child: const Text('查看PDF'), ), ], ) ], ), ), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('课程列表'), ), body: Container( height: double.infinity, child: FirebaseAnimatedList( query: dbRef, itemBuilder: (BuildContext context, DataSnapshot snapshot, Animation<double> animation, int index) { Map student = snapshot.value as Map; student['key'] = snapshot.key; return listItem(student: student); }, ), ), ); } } // 新增的PDF查看页面组件 class PDFViewerPage extends StatelessWidget { final PDFDocument pdfDocument; const PDFViewerPage({super.key, required this.pdfDocument}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('PDF查看器')), body: PDFViewer( document: pdfDocument, zoomSteps: 1, // 可自定义配置:默认缩放比例、页面导航、滚动模式等 ), ); } }
关键修改点
- 加载状态管理:点击按钮后弹出加载指示器,避免用户等待时无反馈
- PDF视图组件:新增
PDFViewerPage页面,使用PDFViewer控件渲染加载完成的PDF文档 - 异常处理:通过try-catch捕获加载失败的情况,用SnackBar提示用户具体错误
- 交互优化:将按钮文本改为更直观的"查看PDF",提升操作辨识度
内容的提问来源于stack exchange,提问作者Rae Sherchan
相关产品推荐
相关产品推荐

