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

如何将Flutter页面转为支持文本选中的PDF(非图片形式)

实现Flutter页面转可选中文本PDF的方案

要生成包含可选中文本的PDF,核心是直接构建PDF原生文本元素,而非将页面截图插入PDF。以下是两种实用方案:

方案一:使用pdf + printing包直接构建PDF内容

这是最可靠的方式,通过pdf包提供的原生PDF组件构建内容,所有文本均为可选中状态。

  1. 添加依赖到pubspec.yaml
dependencies:
  pdf: ^3.10.0
  printing: ^5.12.0
  1. 编写PDF生成代码
    将原Flutter页面的布局逻辑,用pdf包的组件重新实现(常用布局组件如文本、列、行、表格等都有对应实现):
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'package:flutter/services.dart';

Future<void> generateSelectablePdf() async {
  final pdf = pw.Document();

  // 加载自定义字体(可选,若使用系统字体可跳过)
  final customFont = await pw.Font.ttf(await rootBundle.load('assets/fonts/NotoSansSC-Regular.ttf'));

  // 构建PDF页面内容
  pdf.addPage(
    pw.Page(
      pageFormat: PdfPageFormat.a4,
      build: (pw.Context context) {
        return pw.Container(
          padding: pw.EdgeInsets.all(20),
          child: pw.Column(
            crossAxisAlignment: pw.CrossAxisAlignment.start,
            children: [
              pw.Text(
                'Flutter生成的可选中PDF',
                style: pw.TextStyle(
                  font: customFont,
                  fontSize: 24,
                  fontWeight: pw.FontWeight.bold,
                ),
              ),
              pw.SizedBox(height: 16),
              pw.Text(
                '这段文本可以直接选中复制,因为它是PDF原生文本元素,而非图片。',
                style: pw.TextStyle(font: customFont, fontSize: 16),
              ),
              pw.SizedBox(height: 16),
              pw.Column(
                children: [
                  pw.Text('• 列表项1', style: pw.TextStyle(font: customFont, fontSize: 16)),
                  pw.Text('• 列表项2', style: pw.TextStyle(font: customFont, fontSize: 16)),
                ],
              ),
            ],
          ),
        );
      },
    ),
  );

  // 保存PDF到本地
  final tempDir = await getTemporaryDirectory();
  final file = File('${tempDir.path}/selectable_pdf.pdf');
  await file.writeAsBytes(await pdf.save());
  
  // 也可以直接分享PDF
  // await Printing.sharePdf(bytes: await pdf.save(), filename: 'selectable_pdf.pdf');
}

方案二:通过HTML转PDF(适合快速适配现有内容)

如果你的页面内容可以快速转换为HTML格式,可利用pdf包的Html组件渲染,同样生成可选中的文本。

  1. 同样依赖pdf和printing包(同方案一)

  2. 编写HTML转PDF代码

import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';

Future<void> generatePdfFromHtml() async {
  final pdf = pw.Document();
  // 将Flutter页面内容转换为HTML字符串
  final htmlContent = '''
    <h1 style="font-size:24px; font-weight:bold;">HTML转可选中PDF</h1>
    <p style="font-size:16px; margin:16px 0;">这段文本由HTML渲染而来,支持选中复制。</p>
    <ul style="font-size:16px;">
      <li>HTML列表项1</li>
      <li>HTML列表项2</li>
    </ul>
  ''';

  pdf.addPage(
    pw.Page(
      build: (pw.Context context) {
        return pw.Html(
          document: htmlContent,
          // 可选:自定义样式覆盖HTML中的样式
          style: {
            'h1': pw.TextStyle(color: PdfColors.blue),
          },
        );
      },
    ),
  );

  await Printing.sharePdf(bytes: await pdf.save(), filename: 'html_to_pdf.pdf');
}

避坑提示

  • 绝对不要使用截图类插件(如flutter_screenshot)将页面转为图片后插入PDF,这样生成的文本完全不可选中。
  • 若使用自定义字体,必须将字体文件打包到项目中并加载到PDF,否则可能出现字体缺失导致的乱码。
  • 复杂自定义Widget建议用方案一重新实现,确保PDF布局和文本的完整性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 14:36:20