Flutter如何将widget转换为图片并生成PDF文件以便打印?

3
我的Flutter应用程序捕获小部件图像,然后创建PDF文件进行打印。但是,打印结果显示荒谬的内容,如下图所示。
如果您有更好的方法可以将中文字符和QR码图片打印到收据上(使用宽度为75毫米的蓝牙打印机),请告诉我。
以下是我的小部件:
RepaintBoundary(
      key: _renderObjectKey,
      child: ListView(
        children: <Widget>[
          Form(
            key: tableNumberFormKey,
            child:
            ListTile(
              title: TextFormField(
                initialValue: "",
                style: TextStyle(fontSize: 48.0),
                textAlign: TextAlign.center,
                maxLength: 4,
                keyboardType: TextInputType.phone,
                onSaved: (val) => inputTableNumber = val.toString(),
                validator: (val) => val.isEmpty ? '' : null,
                decoration: new InputDecoration(
                  labelText: "輸入檯號",
                  hintText: "例如:12",
                ),
              ),
            ),
          ),
          FlatButton(
            textColor: Colors.blueAccent,
            child: Text(
              "列印 QR CODE",
              style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0),
            ),
            color: Colors.transparent,
            onPressed: () {
              _showQRandPrint();
              SystemChannels.textInput.invokeMethod('TextInput.hide');
            },
          ),
          inputTableNumber == ""
              ? ListTile(title: Text(''),)
              : Center(
            child: QrImage(
              data: qrString,
              size: 300.0,
              version: 10,
              backgroundColor: Colors.white,
            ),
          ),

        ],
      ),
    );

在这里提供创建图像和PDF打印的函数。
void _showQRandPrint() {
    final FormState form = tableNumberFormKey.currentState;

    if (form.validate()) {
      form.save();

      _getWidgetImage().then((img) {
        final pdf = new PDFDocument();
        final page = new PDFPage(pdf, pageFormat: PDFPageFormat(75.0, 100.0));
        final g = page.getGraphics();
        final font = new PDFFont(pdf);

        PDFImage image = new PDFImage(
            pdf,
            image: img,
            width: 75,
            height: 100);
        g.drawImage(image, 0.0, 0.0);

        Printing.printPdf(document: pdf);
      });

    }
    else {
      setState(() {
        inputTableNumber = "";
      });
    }
  }

  Future<Uint8List> _getWidgetImage() async {
    try {
      RenderRepaintBoundary boundary =
      _renderObjectKey.currentContext.findRenderObject();
      ui.Image image = await boundary.toImage(pixelRatio: 3.0);
      ByteData byteData =
      await image.toByteData(format: ui.ImageByteFormat.png);
      var pngBytes = byteData.buffer.asUint8List();
      var bs64 = base64Encode(pngBytes);
      debugPrint(bs64.length.toString());
      return pngBytes;
    } catch (exception) {}
  }

结果图片预览:

在此输入图片描述

屏幕上的小部件是:

在此输入图片描述


4
PDFDocument是PDF文件的文档类型,PDFImage是PDF文件中的图像类型,PDFPageFormat则是PDF页面的格式类型。如果您正在使用库,请包括它。同时展示导入语句以便搜索者了解您所使用的工具。看起来您并没有使用基础的Flutter库。 - Rap
2个回答

6

少量错误:

  • PDFPageFormat(75.0, 100.0) is in pdf native dimensions. If you want milimeters, do:

    PDFPageFormat(75.0 * PDFPageFormat.MM, 100.0 * PDFPageFormat.MM)
    
  • When you declare an image, you have to pass the pixel size

  • And the image cannot be png, but rawRgba data:

    // var img = await image.toByteData(format: ui.ImageByteFormat.rawRgba);
    PDFImage image = new PDFImage(
            pdf,
            image: img.buffer.asUint8List(),
            width: img.width,
            height: img.height);
    
  • the pdf coordinate system has 0,0 at the bottom left corner of the page and still in pdf units so you have to use:

    g.drawImage(image, 100.0 * PDFPageFormat.MM, 0.0, 75.0* PDFPageFormat.MM);
    

    the third parameter set the width. the height is calculated to keep the aspect ratio.

    maybe you will have to adapt this to center the image, but there is an example on the library page.


1
找到了最简单的解决方案。 只需使用aspectRatio调整图像大小,而不是在PdfImage声明中进行调整。 一旦你有了Uint8List文件,请执行以下操作:
final image = PdfImage.file(
  pdf.document,
  bytes: list, //Uint8List
);

然后,在pdf文档本身中使用:


pw.AspectRatio(
              aspectRatio: 3/2,
              child: pw.Image(image)
            )

这就是全部。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接