You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter加载Firebase中PDF文件前如何添加CircularProgressIndicator?

实现PDF加载时展示CircularProgressIndicator的方案

你需要处理两个阶段的加载状态:1. 从Firebase拉取PDF文件的阶段;2. PDF组件渲染本地文件的阶段,以下是完整实现步骤:


方案1:在PDF查看页内部处理加载(体验更优)

步骤1:修改PDFViewerPage代码

调整页面入参,新增加载状态控制,同时覆盖文件拉取、PDF渲染两个阶段的加载提示:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:path/path.dart';
// 替换为你自己的PDFApi导入路径
import 'xxx/xxx/PDFApi.dart';

class PDFViewerPage extends StatefulWidget {
  // 改为接收Firebase的文件路径,而非已加载好的File
  final String firebasePdfUrl;

  const PDFViewerPage({
    Key? key,
    required this.firebasePdfUrl,
  }) : super(key: key);

  @override
  _PDFViewerPageState createState() => _PDFViewerPageState();
}

class _PDFViewerPageState extends State<PDFViewerPage> {
  // 标记是否正在从Firebase拉取文件
  bool _isLoadingFile = true;
  // 标记是否正在渲染PDF
  bool _isRenderingPdf = true;
  // 加载完成的PDF文件
  File? _pdfFile;
  // 加载错误提示
  String? _errorMsg;

  @override
  void initState() {
    super.initState();
    _loadPdfFile();
  }

  // 页面初始化时自动拉取PDF文件
  Future<void> _loadPdfFile() async {
    try {
      final file = await PDFApi.loadFirebase(widget.firebasePdfUrl);
      if (file == null) {
        _errorMsg = '文件加载失败,请检查网络';
      }
      setState(() {
        _pdfFile = file;
        _isLoadingFile = false;
      });
    } catch (e) {
      setState(() {
        _errorMsg = '加载出错:${e.toString()}';
        _isLoadingFile = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final name = basename(widget.firebasePdfUrl);

    return Scaffold(
      appBar: AppBar(
        title: Text(name),
      ),
      body: _buildBody(),
    );
  }

  Widget _buildBody() {
    // 拉取文件阶段加载提示
    if (_isLoadingFile) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
    // 加载错误提示
    if (_errorMsg != null || _pdfFile == null) {
      return Center(
        child: Text(_errorMsg ?? '文件加载失败'),
      );
    }
    // 渲染PDF阶段的加载处理
    return Stack(
      children: [
        PDFView(
          pageSnap: false,
          pageFling: false,
          autoSpacing: false,
          filePath: _pdfFile!.path,
          // PDF渲染完成回调,隐藏加载提示
          onRender: (_) {
            setState(() {
              _isRenderingPdf = false;
            });
          },
        ),
        // 渲染阶段显示加载提示
        if (_isRenderingPdf)
          const Center(
            child: CircularProgressIndicator(),
          )
      ],
    );
  }
}

步骤2:修改按钮点击逻辑

点击后直接跳转PDF查看页,无需在当前页等待文件加载:

onTap: () {
  final url = 'esei.pdf';
  Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => PDFViewerPage(firebasePdfUrl: url),
    ),
  );
},

方案2:不修改PDFViewerPage,仅在按钮处加加载提示

如果不想调整原有PDFViewerPage的逻辑,可以给按钮所在的Widget新增加载状态,点击后直接在按钮位置显示加载动画:

// 按钮所在的State类中新增变量
bool _isLoadingPdf = false;

// 修改按钮部分代码
ElevatedButton(
  onPressed: _isLoadingPdf ? null : () async {
    setState(() {
      _isLoadingPdf = true;
    });
    final url = 'esei.pdf';
    final file = await PDFApi.loadFirebase(url);
    setState(() {
      _isLoadingPdf = false;
    });
    if (file == null) return;
    openPDF(context, file);
  },
  child: _isLoadingPdf 
    ? const CircularProgressIndicator(color: Colors.white)
    : const Text('打开PDF'),
)

内容的提问来源于stack exchange,提问作者ZXERSTON

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 06:18:04