Flutter 热敏打印 模板化实现

2,023 阅读1分钟

前言:

手机端打印一直是一个让人很头疼的问题,用图片打印,图片过大,性能太差.指令打印,可维护性差,调试麻烦.

于是我编写了一个渲染打印指令的库
GitHub链接
具有以下优点

  1. 支持数据绑定
  2. 模板化编写,采用Xml作为设计语言,可阅读性强,无需写死在代码里面,可以热替换
  3. 可预览效果
  4. 支持CPCL与TSL两种指令集
  5. 有Xml Schema,可以检测出编写错误

模板效果

<?xml version="1.0"?>
<page width="640" height="640" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/Im-Kevin/rare_print/master/schema/schema.xsd">
    <font-type fontType="YaHei24" fontBaseWidth="32" fontBaseHeight="41"></font-type>
    <printer-config fontType="YaHei24" fontSize="1">
        <page-info gapmMM="2"/>
    </printer-config>
    <column x="30">
        <stack height="126">
            <image binding="data.brandImage" y="20"/>
            <text align="center" fontSize="2" y="76">产品标识卡</text>
        </stack>
        <column>
            <row height="50" y="30">
                <text width="90">品名:</text>
                <text binding="data.familyName"></text>
            </row>
            <row height="50" y="18">
                <row width="310">
                    <text width="90">型号:</text>
                    <text binding="data.familyStyleName"></text>
                </row>
                <row width="310">
                    <text width="90">颜色:</text>
                    <text binding="data.colorName"></text>
                </row>
            </row>
            <row height="50" y="18">
                <text width="90">规格:</text>
                <text binding="data.specName"></text>
            </row>
            <row>
                <column width="400">
                    <row height="50" y="18">
                        <text width="90">数量:</text>
                        <text binding="data.qty" width="auto"></text>
                        <text binding="data.um" width="100"></text>
                    </row>
                    <row height="50" y="18">
                        <text width="150">生产部门:</text>
                        <text binding="data.productionOu"></text>
                    </row>
                    <row height="50" y="18">
                        <text width="150">检 验 员:</text>
                        <text binding="data.inspectors"></text>
                    </row>
                    <row height="50" y="18">
                        <text width="150">生产日期:</text>
                        <text binding="data.date" format="yyyy年MM月dd日"></text>
                    </row>
                </column> 
                <column>
                    <qrcode 
                        binding="'123213' + data.uniqueCode"
                        width="200"
                        height="200" 
                        imagePaint="true"></qrcode>
                    <text width="200" height="50" y="22" align="center" binding="data.uniqueCode"></text>
                </column>
            </row>
        </column>
    </column>
</page>

使用方法:

安装依赖

dependencies:
  rare_print: ^0.1.2

导入包

import 'package:rare_print/rare_print.dart';

编写自己的打印模板

实现打印功能

    final demoXml = '<page width="880">...</page>' // 模板
    var control = ControlBase.create(demoXml); // 解析模板

    var jsonData = json.decode(dataSource); // 将json数据源转换成 Map

    control.setDataSource(DataSource(jsonData)); // 设置数据源

    control.performLayout(PrinterConstraints(maxWidth: 837)); // 计算布局样式
    CPCLCanvas canvas = CPCLCanvas(); // 创建画布
    canvas.pageSize = control.actualSize; // 设置画布大小
    canvas.reset(); // 重置画布

    control.paint(canvas, PrinterOffset.zero); // 渲染画布

    canvas.end(); // 标记画布渲染结束

    io.send(canvas.toCommand); // 输出具体指令

实现预览功能

    ControlBase control;
    @override
    void initState() {
        super.initState();
        final demoXml = '<page width="880">...</page>' // 模板
        control = ControlBase.create(demoXml); // 解析模板

        var jsonData = json.decode(dataSource); // 将json数据源转换成 Map

        control.setDataSource(DataSource(jsonData)); // 设置数据源
    }

    @override
    Widget build(BuildContext context) {
        return PreviewWidget( // 使用PreviewWidget展示效果
            control: control
        );
    }