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

Flutter使用flutter_pdfview时CircularProgressIndicator显示异常求助

修复方案

问题根因

  • 进度条与PDF同时出现:flutter_pdfview依托原生视图渲染,加载过程中原生视图会先渲染空白占位,挡住了上层的Flutter进度指示器,直到PDF内容渲染完成才和进度条同时展示
  • 进度条持续加载不消失:部分场景下onRender回调存在兼容问题,加载小体积PDF、本地缓存PDF时不会触发该回调,导致isReady状态永远为false

修复后完整代码

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:flutter_web_browser/flutter_web_browser.dart';
import 'package:path/path.dart';
import 'dart:async';

openBrowserTab() async {
  await FlutterWebBrowser.openWebPage(
      url:
          "https://docs.google.com/forms/d/e/1FAIpQLScdrUJaGxFCLSJV7Njg8WZlqLZOh40Jq000hggexoRjA1-8nQ/viewform?usp=sf_link",
      customTabsOptions: CustomTabsOptions(
        toolbarColor: Colors.lightBlueAccent,
      ));
}

class PDFViewerPage extends StatefulWidget {
  final File file;

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

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


class _PDFViewerPageState extends State<PDFViewerPage> {
  bool isReady = false;
  final Completer<PDFViewController> _controller = Completer<PDFViewController>();
  String errorMessage = '';

  @override
  void initState() {
    super.initState();
    // 3秒兜底超时,避免回调异常导致进度条一直显示
    Future.delayed(const Duration(seconds: 3), () {
      if(mounted && !isReady) {
        setState(() {
          isReady = true;
        });
      }
    });
  }

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

    return Scaffold(
      appBar: AppBar(
        title: Text(name),
        actions: <Widget>[
          IconButton(
            icon: Icon(
              Icons.error,
              color: Colors.yellow,
            ),
            onPressed: () => openBrowserTab(),
          )
        ],
      ),
      body: Stack(
        children: <Widget>[
          Offstage(
            offstage: !isReady,
            child: PDFView(
              pageSnap: false,
              pageFling: false,
              autoSpacing: false,
              filePath: widget.file.path,
              onRender: (_pages) {
                setState(() {
                  isReady = true;
                });
              },
              onPageChanged: (page, total) {
                // 兜底onRender不触发的场景
                if(!isReady) {
                  setState(() {
                    isReady = true;
                  });
                }
              },
              onError: (error) {
                setState(() {
                  errorMessage = error.toString();
                });
                print(error.toString());
              },
              onPageError: (page, error) {
                setState(() {
                  errorMessage = '$page: ${error.toString()}';
                });
                print('$page: ${error.toString()}');
              },
              onViewCreated: (PDFViewController pdfViewController) {
                _controller.complete(pdfViewController);
              },
            ),
          ),
          errorMessage.isEmpty
              ? !isReady
                  ? const Center(
                      child: CircularProgressIndicator(),
                    )
                  : const SizedBox.shrink()
              : const Center(
                  child: Text('Please check your internet connection'),
                ),
        ],
      ),
    );
  }
}

核心修改点

  • 用Offstage包裹PDFView,加载完成前隐藏原生视图占位,只展示进度指示器,彻底解决两者同时出现的问题
  • 新增onPageChanged兜底回调,兼容onRender不触发的场景
  • 新增3秒超时兜底逻辑,就算所有回调都异常,也会自动隐藏进度条
  • 替换空Container为更轻量的SizedBox.shrink()优化性能

内容的提问来源于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 10:45:03