欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Flutter實現(xiàn)打印功能的示例詳解

 更新時間:2024年03月21日 09:33:58   作者:Jimmy  
這篇文章主要為大家詳細(xì)介紹了如何通過?Flutter?實現(xiàn)調(diào)用打印機(jī)打印的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

開發(fā)環(huán)境

  • Flutter Version:3.16.4
  • 系統(tǒng):macOS Sonoma - Apple M1 芯片
  • Android Studio: 17.0.7

我們通過 flutter create project_name 創(chuàng)建項目。

我們?nèi)绾未蛴?/h2>

關(guān)于調(diào)起 printer 打印的功能。我們有以下的想法:

  • 打印當(dāng)前路由頁面的內(nèi)容,類似于網(wǎng)頁的調(diào)用 window.print 方式打印
  • 打印頁面中指定的 widget 的內(nèi)容
  • 打印重組的 widget 的內(nèi)容
  • 將頁面指定的 widget 轉(zhuǎn)化為 image 之后,再調(diào)起打印

針對第一點,我們并沒有發(fā)現(xiàn)在 app 中有類似 window.print 的方法;而對第二點,我們也不能指定頁面中 widget 進(jìn)行打印。剩下的第三點和第四點,我們都可以實現(xiàn)。

接下來,我們將應(yīng)用 flutter printing 包,來演示后兩種實現(xiàn)方式。

引入 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 是可選,筆者在調(diào)試 macos 的項目時候用到。printing 在編寫本文時候的版本是 ^5.12.0,請以 官網(wǎng) 版本為主

然后,我們可以通過 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 相關(guān)包。

因為我們是在 macos 上進(jìn)行調(diào)試,我們還需要在 macos/Runner/Release.entitlementsmacos/Runner/DebugProfile.entitlements 文件中添加內(nèi)容:

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

如果是其他平臺開發(fā)調(diào)試,請參考 printing 引入相關(guān)的內(nèi)容。

之后我們在 main.dart 中實現(xiàn)相關(guān)的邏輯:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Print Demo'),
    ),
    body: Center(
      child: ElevatedButton(
        onPressed: _printPdf,
        child: Text('Print'),
      ),
    ),
  );
}

上面我們編寫了相關(guān)的 widget,展示一個 Print 按鈕,當(dāng)點擊按鈕時候,觸發(fā)方法 _printPdf,該方法的實現(xiàn)如下

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,然后調(diào)起打印機(jī) Printing.layoutPdf,動態(tài)如下

那么,對于復(fù)雜的內(nèi)容,如果我們還是編寫自定義的 widgets 的話,那不切實際,維護(hù)成本高。那么,我們有什么方法打印它呢?這就是下面我們要介紹的了~

widgets 內(nèi)容轉(zhuǎn) image,再打印 image

我們直接將頁面上的 widgets 內(nèi)容轉(zhuǎn)換為 image,再結(jié)合上面提及的打印組合的 widgets 處理即可。

將 widgets 內(nèi)容轉(zhuǎn) 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 來指定了重繪的區(qū)域為 200*200 的文本值。當(dāng)我們點擊 ElevatedButton 掛件時候,會觸發(fā) _capturePng 方法。在 _capturePng 方法中,我們將區(qū)域內(nèi)的內(nèi)容轉(zhuǎn)換為圖像,并且,將圖像轉(zhuǎn)為位數(shù)據(jù),給 _imageBytes 賦值,展現(xiàn)在頁面上。相關(guān) Gif 圖如下

整合 Image 掛件

在上面的例子中,我們保存了生成的圖數(shù)據(jù)。接下來,我們將該圖片打印出來。上面的代碼,我們在原始基礎(chǔ)上更改:

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 的內(nèi)容,并調(diào)起打印機(jī)打印~

為了方便演示,看到邊界,我們更改了下 UI

當(dāng)然,我們可以設(shè)定其打印的邊距和指定內(nèi)容的方向等:

pw.Page(
  orientation: pw.PageOrientation.landscape, // 內(nèi)容的方向
  margin: pw.EdgeInsets.all(16.0), // 邊距
  ...
)

以上就是Flutter實現(xiàn)打印功能的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Flutter打印的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論