You need to enable JavaScript to run this app. Android蓝牙连接ESC/POS打印机 如何调小字号并取消下划线打印
优惠活动
大模型
产品
解决方案
定价
更多

Android蓝牙连接ESC/POS打印机 如何调小字号并取消下划线打印

核心问题定位

从你提供的代码和打印表现,两个异常(字号过大、全文本带下划线)都是指令参数不符合ESC/POS标准导致的:

下划线无法消除的根源

  • 你的PrinterCommands类完全没有定义下划线控制指令,整个打印流程也从未下发过「关闭下划线」的指令,打印机保留了默认的下划线开启状态,所有打印内容自然带线。
  • 标准ESC/POS协议中,控制下划线的指令为ESC - n:参数n=0x00表示完全关闭下划线,n=0x01/0x02表示开启1点/2点宽度的下划线。

字号过大的根源

  • 你用来设置字号的ESC ! n指令(即代码中0x1B, 0x21, 参数值)完全用错了参数位定义:

    标准ESC ! n的位功能定义:

    • bit 0(对应值0x01):切换A/B字体
    • bit 3(对应值0x08):开启/关闭垂直倍高
    • bit 4(对应值0x10):开启/关闭水平倍宽
  • 你代码里size=0(预期普通字号)时发送的参数是0x03,同时触发了两个非预期的位效果,根本不是正常字号;用来对应大字号的参数0x10只单独开启了水平倍宽,没有匹配你预期的字号层级。
  • 另外你resetPrint方法里的FS_FONT_ALIGN指令参数错误,给汉字模式强行开启了倍高效果,进一步放大了实际打印的字号。
具体修改方案

1. 补全并修正PrinterCommands类的指令定义

删掉原有错误的指令,替换为符合协议的版本:

public class PrinterCommands { 
    public static final byte LF = 0x0A;
    public static byte[] FEED_LINE = {10};
    public static final byte[] ESC_FONT_COLOR_DEFAULT = new byte[] { 0x1B, 'r',0x00 };
    // 替换原有错误的FS_FONT_ALIGN,改为汉字模式重置指令
    public static final byte[] FS_FONT_RESET = new byte[] { 0x1C, 0x21, 0x00 };
    public static final byte[] ESC_ALIGN_LEFT = new byte[] { 0x1b, 'a', 0x00 };
    public static final byte[] ESC_ALIGN_RIGHT = new byte[] { 0x1b, 'a', 0x02 };
    public static final byte[] ESC_ALIGN_CENTER = new byte[] { 0x1b, 'a', 0x01 };
    public static final byte[] ESC_CANCEL_BOLD = new byte[] { 0x1B, 0x45, 0 };
    // 新增:关闭下划线的标准指令
    public static final byte[] ESC_CANCEL_UNDERLINE = new byte[] { 0x1B, 0x2D, 0x00 };
}

2. 修正初始化重置逻辑,从打印开头就关闭错误格式

把原有resetPrint方法中的错误逻辑替换掉,每次打印前就强制清掉残留的格式设置:

public void resetPrint() {
    try{
        // 打印前依次下发全量格式重置指令
        outputStream.write(PrinterCommands.ESC_CANCEL_UNDERLINE);
        outputStream.write(PrinterCommands.FS_FONT_RESET);
        outputStream.write(PrinterCommands.ESC_ALIGN_LEFT);
        outputStream.write(PrinterCommands.ESC_CANCEL_BOLD);
        // 强制将默认字号设置为普通大小
        outputStream.write(new byte[]{0x1B, 0x21, 0x00});
        outputStream.write(PrinterCommands.LF);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3. 修正printCustom方法的字号参数,适配58mm打印纸

结合58mm纸的可打印宽度(约32个普通英文字符位),把原有错误的字号参数替换为协议标准值:

private void printCustom(String msg, int size, int align) {
    try {
        // 按需求匹配对应字号的标准参数
        switch (size){
            case 0: // 普通正文:无倍高/倍宽,适配常规文本
                outputStream.write(new byte[]{0x1B, 0x21, 0x00});
                break;
            case 1: // 中号文本:仅垂直倍高,适合地址、联系方式
                outputStream.write(new byte[]{0x1B, 0x21, 0x08});
                break;
            case 2: // 大号标题:垂直+水平倍宽,适合店名
                outputStream.write(new byte[]{0x1B, 0x21, 0x18});
                break;
            case 3: // 特大号文本:双倍高+双倍宽,适合主标题
                outputStream.write(new byte[]{0x1B, 0x21, 0x18});
                break;
        }

        // 原有的对齐逻辑保持不变即可
        switch (align){
            case 0:
                outputStream.write(PrinterCommands.ESC_ALIGN_LEFT);
                break;
            case 1:
                outputStream.write(PrinterCommands.ESC_ALIGN_CENTER);
                break;
            case 2:
                outputStream.write(PrinterCommands.ESC_ALIGN_RIGHT);
                break;
        }
        // 每段打印前强制确认下划线关闭,避免状态漂移
        outputStream.write(PrinterCommands.ESC_CANCEL_UNDERLINE);
        outputStream.write(msg.getBytes());
        outputStream.write(PrinterCommands.LF);
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(this,e.getLocalizedMessage(),Toast.LENGTH_SHORT).show();
    }
}

落地注意事项

  • 你代码中直接调用的printText方法(用来打印订单明细、总金额的逻辑),需要在方法开头同样下发ESC_CANCEL_UNDERLINE和普通字号指令,不然这些文本会继承默认的格式状态,依然出现大字号、带下划线的问题。
  • 58mm宽度的打印纸,不建议设置超过2倍倍宽的字号,不然打印内容会超出纸边被截断。
  • 打印机的格式状态是持久保存的,不会在每次打印后自动复位,所以一定要在每次打印流程的最开头下发全量重置指令,避免上一次打印的格式残留到本次输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 04:36:01