当前位置: 代码网 > it编程>App开发>Android > Flutter实现打印功能的示例详解

Flutter实现打印功能的示例详解

2024年05月15日 Android 我要评论
开发环境flutter version:3.16.4系统:macos sonoma-apple m1芯片android studio: 17.0.7我们通过 flutter create projec

开发环境

  • flutter version:3.16.4
  • 系统:macos sonoma - apple m1 芯片
  • android studio: 17.0.7

我们通过 flutter create project_name 创建项目。

我们如何打印

关于调起 printer 打印的功能。我们有以下的想法:

  • 打印当前路由页面的内容,类似于网页的调用 window.print 方式打印
  • 打印页面中指定的 widget 的内容
  • 打印重组的 widget 的内容
  • 将页面指定的 widget 转化为 image 之后,再调起打印

针对第一点,我们并没有发现在 app 中有类似 window.print 的方法;而对第二点,我们也不能指定页面中 widget 进行打印。剩下的第三点和第四点,我们都可以实现。

接下来,我们将应用 flutter printing 包,来演示后两种实现方式。

引入 printing 包

引入 printing 很简单:

将 printing 包添加到我们的 pubspec.yaml 文件:

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^2.0.13 # optional
  flutter_inappwebview: ^5.3.2 # optional

  # the following adds the cupertino icons font to your application.
  # use with the cupertinoicons class for ios style icons.
  cupertino_icons: ^1.0.2
  printing: ^5.12.0

webview_flutterflutter_inappwebview 是可选,笔者在调试 macos 的项目时候用到。printing 在编写本文时候的版本是 ^5.12.0,请以 官网 版本为主

然后,我们可以通过 flutter pub get 来获取包

打印组合的 widgets

下面,我们以一个简单的案例来说说怎么使用该包,并怎么打印组合的 widget

我们直接在项目的 main.dart 上操作:

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

上面引入 pdfprinting 相关包。

因为我们是在 macos 上进行调试,我们还需要在 macos/runner/release.entitlementsmacos/runner/debugprofile.entitlements 文件中添加内容:

<key>com.apple.security.print</key>
<true/>

如果是其他平台开发调试,请参考 printing 引入相关的内容。

之后我们在 main.dart 中实现相关的逻辑:

@override
widget build(buildcontext context) {
  return scaffold(
    appbar: appbar(
      title: text('print demo'),
    ),
    body: center(
      child: elevatedbutton(
        onpressed: _printpdf,
        child: text('print'),
      ),
    ),
  );
}

上面我们编写了相关的 widget,展示一个 print 按钮,当点击按钮时候,触发方法 _printpdf,该方法的实现如下

future<void> _printpdf() async {
  try {
    final doc = pw.document();
    
    doc.addpage(pw.page(
      pageformat: pdfpageformat.a4,
      build: (pw.context context) {
        return pw.center(
          child: pw.text('hello jimmy'),
        );
      }
    ));
    
    await printing.layoutpdf(  
      onlayout: (pdfpageformat format) async => doc.save(),  
    );
  } catch (e) {
    print(e);
  } 
}

在这个方法中,我们在 addpage 中重新组合了需要打印的 widgets,然后调起打印机 printing.layoutpdf,动态如下

那么,对于复杂的内容,如果我们还是编写自定义的 widgets 的话,那不切实际,维护成本高。那么,我们有什么方法打印它呢?这就是下面我们要介绍的了~

widgets 内容转 image,再打印 image

我们直接将页面上的 widgets 内容转换为 image,再结合上面提及的打印组合的 widgets 处理即可。

将 widgets 内容转 image

先上代码:

import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';

class _myhomepagestate extends state<myhomepage> {
  final globalkey boundarykey = globalkey();
  uint8list _imagebytes = uint8list(0);

  @override
  widget build(buildcontext context) {
    return scaffold(
      appbar: appbar(
        title: text('widget to image demo'),
      ),
      body: center(
        child: column(
          mainaxisalignment: mainaxisalignment.center,
          children: <widget>[
            repaintboundary(
              key: boundarykey,
              child: container(
                width: 200,
                height: 200,
                color: colors.blue,
                child: center(
                  child: text(
                    'hello, jimmy!',
                    style: textstyle(
                      color: colors.white,
                      fontsize: 24,
                    ),
                  ),
                ),
              ),
            ),
            sizedbox(height: 20),
            elevatedbutton(
              onpressed: _capturepng,
              child: text('capture image'),
            ),
            sizedbox(height: 20),
            if (!_imagebytes.isempty)
              image.memory(
                _imagebytes,
                width: 200,
                height: 200,
              ),
          ],
        ),
      ),
    );
  }

  future<void> _capturepng() async {
    try {
      renderrepaintboundary? boundary =
      boundarykey.currentcontext?.findrenderobject() as renderrepaintboundary?;
      ui.image? image = await boundary?.toimage(pixelratio: 3.0);
      bytedata? bytedata =
      await image?.tobytedata(format: ui.imagebyteformat.png);
      setstate(() {
        _imagebytes = bytedata!.buffer.asuint8list(); // 赋值
      });
    } catch (e) {
      print(e);
    }
  }
}

在代码中,我们用 repaintboundary 来指定了重绘的区域为 200*200 的文本值。当我们点击 elevatedbutton 挂件时候,会触发 _capturepng 方法。在 _capturepng 方法中,我们将区域内的内容转换为图像,并且,将图像转为位数据,给 _imagebytes 赋值,展现在页面上。相关 gif 图如下

整合 image 挂件

在上面的例子中,我们保存了生成的图数据。接下来,我们将该图片打印出来。上面的代码,我们在原始基础上更改:

elevatedbutton(
  onpressed: () => _capturepng(context),
  child: text('capture image'),
),

引入包:

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

然后补充 _capturepng 方法:

future<void> _capturepng(buildcontext ctx) async {
  try {
    // 添加 print
    final doc = pw.document();

    renderrepaintboundary? boundary = boundarykey.currentcontext
      ?.findrenderobject() as renderrepaintboundary?;
    ui.image? image = await boundary?.toimage(pixelratio: 3.0);
    bytedata? bytedata =
      await image?.tobytedata(format: ui.imagebyteformat.png);

    final pageformat = pdfpageformat.a4;
  
    print(mediaquery.of(ctx).size.height); // 测试打印界面的高度

    doc.addpage(pw.page(
      pageformat: pageformat,
      orientation: pw.pageorientation.landscape,
      build: (pw.context context) {
        return pw.center(
          child: pw.image( // 图像挂件
            pw.memoryimage(_imagebytes),
            width: pageformat.height - 20,
            fit: pw.boxfit.fitwidth,
          ),
        );
      }));

    // 打印
    await printing.layoutpdf(
      onlayout: (pdfpageformat format) async => doc.save(),
    );
  } catch (e) {
    print(e);
  }
}

上面,我们通过 pw.memoryimage(_imagebytes) 指定 image 的内容,并调起打印机打印~

为了方便演示,看到边界,我们更改了下 ui

当然,我们可以设定其打印的边距和指定内容的方向等:

pw.page(
  orientation: pw.pageorientation.landscape, // 内容的方向
  margin: pw.edgeinsets.all(16.0), // 边距
  ...
)

以上就是flutter实现打印功能的示例详解的详细内容,更多关于flutter打印的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com