之前做了个pos机的项目,当时因为是给缅甸客户用的,界面用的是缅甸文,但是打印机不支持缅甸文,所以只能以打印图片的方式实现;所以利用canvas直接画小票图片,直接打印图片实现打印功能;下面是利用canvas画图的工具类:
public class ImgUtil {// public static void saveBitmap(String bitName, Bitmap mBitmap) {// File f = new File("/sdcard/" + bitName + ".png");// try {// f.createNewFile();// } catch (IOException e) {// e.printStackTrace();// }// FileOutputStream fOut = null;// try {// fOut = new FileOutputStream(f);// } catch (FileNotFoundException e) {// e.printStackTrace();// }// press(pressFormat.PNG, 100, fOut);// try {// fOut.flush();// } catch (IOException e) {// e.printStackTrace();// }// try {// fOut.close();// } catch (IOException e) {// e.printStackTrace();// }// Log.i("msg", "图片路径:" + f.getAbsolutePath());// }/*** 获取文本的宽度** @param paint* @param text* @return*/public static int getFontWidth(Paint paint, String text) {Rect rect = new Rect();paint.getTextBounds(text, 0, text.length(), rect);return rect.width();}/*** 获取文本的高度** @param paint* @param text* @return*/public static int getFontHeight(Paint paint, String text) {Rect rect = new Rect();paint.getTextBounds(text, 0, text.length(), rect);return rect.height();}/*** 获取打印图片的菜品需要打印的高度** @param list* @param normalFontHeight* @param perLineDistance* @return*/public static int getProBmpHeight(ArrayList<ProductModel> list,int normalFontHeight, int perLineDistance, boolean toKitchen) {int h = 0;for (int i = 0; i < list.size(); i++) {//根据菜品文本长度显示多行int lines = getProShowLine(list.get(i).getProductName());for (int j = 0; j < lines; j++) {h = h + normalFontHeight + perLineDistance;}//如果是发送到厨房的需要计算备注的高度if (toKitchen) {//显示备注lines = getProShowLine(list.get(i).getChoseLable());for (int j = 0; j < lines; j++) {h = h + normalFontHeight + perLineDistance;}}h = h + perLineDistance;//菜品之间距离大点,方便区分}return h;}/*** 把pos端小票信息转成图片** @return*/public static Bitmap posTickTopBmp(Activity activity, ArrayList<ProductModel> pros) {Paint paint = new Paint();paint.setTextSize(30);paint.setColor(Color.BLACK);paint.setStyle(Paint.Style.FILL);paint.setTypeface(Typeface.DEFAULT_BOLD);//店铺名称字体的高度final int restaurantNameHeight = getFontHeight(paint, "店铺");//小字黑体文本的高度paint.setTextSize(20);final int blackFontHeight = getFontHeight(paint, "店铺");//小字正常字体的高度paint.setTypeface(Typeface.DEFAULT);final int normalFontHeight = getFontHeight(paint, "店铺");//行与行之间的空白距离final int perLineDistance = 20;//字体之间的距离final int perFontDistance = 20;//可打印图片的最大宽度和高度;final int bmpWidth = 576, bmpHeight = 436 + 565 + getProBmpHeight(pros, normalFontHeight, perLineDistance, false);final int topBlank = 100;//电话和日期之间的空白final int bottomBlank = 200;//底部留白(可能要撕纸,需要留白)Bitmap bmp = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bmp);canvas.drawColor(Color.WHITE);int w;int y;String str;//开始画图paint.setTextSize(30);paint.setTypeface(Typeface.DEFAULT_BOLD);str = "店铺名称";w = getFontWidth(paint, str);canvas.drawText(str, bmpWidth / 2 - w / 2, restaurantNameHeight, paint);paint.setTextSize(20);paint.setTypeface(Typeface.DEFAULT);str = "电话:18546544545";w = getFontWidth(paint, str);canvas.drawText(str, bmpWidth / 2 - w / 2, restaurantNameHeight + normalFontHeight + perLineDistance, paint);str = "日期: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w = getFontWidth(paint, str);y = blackFontHeight + normalFontHeight + restaurantNameHeight + topBlank;canvas.drawText(str, 0, y, paint);str = "/03/25 15:50";paint.setTypeface(Typeface.DEFAULT);canvas.drawText(str, w + perFontDistance, y, paint);str = "区域: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w = getFontWidth(paint, str);y = blackFontHeight * 2 + normalFontHeight + restaurantNameHeight + topBlank + perLineDistance * 1;canvas.drawText(str, 0, y, paint);paint.setTypeface(Typeface.DEFAULT);str = "大厅";canvas.drawText(str, w + perFontDistance, y, paint);str = "桌位: ";paint.setTypeface(Typeface.DEFAULT_BOLD);int w1 = getFontWidth(paint, str);paint.setTypeface(Typeface.DEFAULT);int w2 = getFontWidth(paint, "A04");paint.setTypeface(Typeface.DEFAULT_BOLD);canvas.drawText(str, bmpWidth - (w1 + w2) - 50, y, paint);//50是距离右边纸的距离paint.setTypeface(Typeface.DEFAULT);canvas.drawText("A04", bmpWidth - w2 - 50 + perFontDistance, y, paint);str = "上座人数: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w = getFontWidth(paint, str);y = blackFontHeight * 3 + normalFontHeight + restaurantNameHeight + topBlank + perLineDistance * 2;canvas.drawText(str, 0, y, paint);paint.setTypeface(Typeface.DEFAULT);canvas.drawText("5人", w + perFontDistance, y, paint);str = "服务员: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w1 = getFontWidth(paint, str);paint.setTypeface(Typeface.DEFAULT);w2 = getFontWidth(paint, "Anny");paint.setTypeface(Typeface.DEFAULT_BOLD);canvas.drawText(str, bmpWidth - (w1 + w2) - 50, y, paint);paint.setTypeface(Typeface.DEFAULT);canvas.drawText("Anny", bmpWidth - w2 - 50 + perFontDistance, y, paint);str = "订单号: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w = getFontWidth(paint, str);y = blackFontHeight * 4 + normalFontHeight + restaurantNameHeight + topBlank + perLineDistance * 3;canvas.drawText(str, 0, y, paint);paint.setTypeface(Typeface.DEFAULT);canvas.drawText("4884977449494949494", w + perFontDistance, y, paint);paint.setTypeface(Typeface.DEFAULT_BOLD);//画线y = y + perLineDistance * 2;canvas.drawLine(0, y, bmpWidth, y, paint);//title(菜品、单价、数量、小计)y = y + perLineDistance * 2;canvas.drawText("菜品", 20, y, paint);canvas.drawText("单价", bmpWidth - getFontWidth(paint, "小计") - 50 - 100 - 100, y, paint);canvas.drawText("数量", bmpWidth - getFontWidth(paint, "小计") - 50 - 100, y, paint);canvas.drawText("小计", bmpWidth - getFontWidth(paint, "小计") - 50, y, paint);//画线y = y + blackFontHeight;canvas.drawLine(0, y, bmpWidth, y, paint);// ArrayList<String> list = new ArrayList<>();// list.add("麻辣小龙虾");// list.add("100");// list.add("2");// list.add("1000");paint.setTypeface(Typeface.DEFAULT);y = y + perLineDistance * 2;Log.i("msg", "上面的高度:" + y);//下面是画菜品文本for (int i = 0; i < pros.size(); i++) {//先画后面的值,菜品名称后面画,因为菜品名称可能多行显示,以菜品显示高度为准;// int dishMoneyWh = getFontWidth(paint, "¥" + list.get(3));// canvas.drawText("¥" + list.get(1), bmpWidth - dishMoneyWh - 50 - 100 - 100, y, paint);// canvas.drawText(list.get(2), bmpWidth - dishMoneyWh - 50 - 100, y, paint);// canvas.drawText("¥" + list.get(3), bmpWidth - dishMoneyWh - 50, y, paint);// int dishMoneyWh = getFontWidth(paint, "¥" + pros.get(i).getPrice() * pros.get(i).getCount());canvas.drawText("¥" + pros.get(i).getPrice(), bmpWidth - getFontWidth(paint, "小计") - 50 - 100 - 100, y, paint);canvas.drawText(String.valueOf(pros.get(i).getCount()), bmpWidth - getFontWidth(paint, "小计") - 50 - 100, y, paint);canvas.drawText("¥" + pros.get(i).getPrice() * pros.get(i).getCount(), bmpWidth - getFontWidth(paint, "小计") - 50, y, paint);//根据菜品文本长度显示多行// int lines = getProShowLine(list.get(0));int lines = getProShowLine(pros.get(i).getProductName());for (int j = 0; j < lines; j++) {//str = getSubPro(list.get(0), j, lines);str = getSubPro(pros.get(i).getProductName(), j, lines);canvas.drawText(str, 0, y, paint);y = y + normalFontHeight + perLineDistance;}y = y + perLineDistance;//菜品之间距离大点,方便区分}Log.i("msg", "中间的高度:" + y);//画线canvas.drawLine(0, y, bmpWidth, y, paint);//下面是各种金额y = y + perLineDistance * 2;paint.setTypeface(Typeface.DEFAULT_BOLD);canvas.drawText("店铺实收", 0, y, paint);canvas.drawText("¥1000", bmpWidth - getFontWidth(paint, "¥1000") - 50, y, paint);y = y + blackFontHeight + perLineDistance;canvas.drawText("消费税", 0, y, paint);canvas.drawText("¥50", bmpWidth - getFontWidth(paint, "¥50") - 50, y, paint);y = y + blackFontHeight + perFontDistance;canvas.drawText("服务费", 0, y, paint);canvas.drawText("¥100", bmpWidth - getFontWidth(paint, "¥100") - 50, y, paint);y = y + blackFontHeight + perFontDistance;canvas.drawText("折扣金额", 0, y, paint);canvas.drawText("-¥100", bmpWidth - getFontWidth(paint, "-¥100") - 50, y, paint);//画线y = y + blackFontHeight + perFontDistance;canvas.drawLine(0, y, bmpWidth, y, paint);paint.setTypeface(Typeface.DEFAULT_BOLD);paint.setTextSize(25);y = y + blackFontHeight + perFontDistance;canvas.drawText("最终实收", 0, y, paint);canvas.drawText("¥20000", bmpWidth - getFontWidth(paint, "¥20000") - 50, y, paint);paint.setTypeface(Typeface.DEFAULT_BOLD);paint.setTextSize(20);y = y + 100;str = "Powered Zpos";w = getFontWidth(paint, str);canvas.drawText(str, bmpWidth / 2 - w / 2, y, paint);y = y + normalFontHeight;str = "Thank you,Please com again";w = getFontWidth(paint, str);canvas.drawText(str, bmpWidth / 2 - w / 2, y, paint);y = y + bottomBlank;Log.i("msg", "最后的高度:" + y);return bmp;}public static Bitmap kitchenTickToBmp(ArrayList<ProductModel> pros) {Paint paint = new Paint();paint.setTextSize(30);paint.setColor(Color.BLACK);paint.setStyle(Paint.Style.FILL);paint.setTypeface(Typeface.DEFAULT_BOLD);final int kitchenNameHeight = getFontHeight(paint, "厨位");//小字黑体文本的高度paint.setTextSize(20);final int blackFontHeight = getFontHeight(paint, "厨位");//小字正常字体的高度paint.setTypeface(Typeface.DEFAULT);final int normalFontHeight = getFontHeight(paint, "厨位");//行与行之间的空白距离final int perLineDistance = 20;//字体之间的距离final int perFontDistance = 20;//可打印图片的最大宽度和高度;final int bmpWidth = 384, bmpHeight = 386 + 250 + getProBmpHeight(pros, normalFontHeight, perLineDistance, true);final int topBlank = 50;//厨位和日期之间的空白高度final int bottomBlank = 200;//底部留白(可能要撕纸,需要留白)Bitmap bmp = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bmp);canvas.drawColor(Color.WHITE);int w;int y;String str;//开始画图paint.setTextSize(30);paint.setTypeface(Typeface.DEFAULT_BOLD);str = "厨位: 1号厨位";canvas.drawText(str, 0, kitchenNameHeight, paint);paint.setTextSize(20);str = "日期: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w = getFontWidth(paint, str);y = kitchenNameHeight + topBlank;canvas.drawText(str, 0, y, paint);str = "/03/25 15:50";paint.setTypeface(Typeface.DEFAULT);canvas.drawText(str, w + perFontDistance, y, paint);str = "区域: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w = getFontWidth(paint, str);y = blackFontHeight + kitchenNameHeight + topBlank + perLineDistance * 1;canvas.drawText(str, 0, y, paint);paint.setTypeface(Typeface.DEFAULT);str = "大厅";canvas.drawText(str, w + perFontDistance, y, paint);str = "桌位: ";paint.setTypeface(Typeface.DEFAULT_BOLD);int w1 = getFontWidth(paint, str);paint.setTypeface(Typeface.DEFAULT);int w2 = getFontWidth(paint, "A04");paint.setTypeface(Typeface.DEFAULT_BOLD);canvas.drawText(str, bmpWidth - (w1 + w2) - 50, y, paint);//50是距离右边纸的距离paint.setTypeface(Typeface.DEFAULT);canvas.drawText("A04", bmpWidth - w2 - 50 + perFontDistance, y, paint);str = "上座人数: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w = getFontWidth(paint, str);y = blackFontHeight * 2 + kitchenNameHeight + topBlank + perLineDistance * 2;canvas.drawText(str, 0, y, paint);paint.setTypeface(Typeface.DEFAULT);canvas.drawText("5人", w + perFontDistance, y, paint);str = "服务员: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w1 = getFontWidth(paint, "服务员:");paint.setTypeface(Typeface.DEFAULT);w2 = getFontWidth(paint, "Anny");paint.setTypeface(Typeface.DEFAULT_BOLD);canvas.drawText("服务员:", bmpWidth - (w1 + w2) - 50, y, paint);paint.setTypeface(Typeface.DEFAULT);canvas.drawText("Anny", bmpWidth - w2 - 50 + perFontDistance, y, paint);str = "订单号: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w = getFontWidth(paint, str);y = blackFontHeight * 3 + kitchenNameHeight + topBlank + perLineDistance * 3;canvas.drawText(str, 0, y, paint);paint.setTypeface(Typeface.DEFAULT);canvas.drawText("4884977449494949494", w + perFontDistance, y, paint);str = "厨房单号: ";paint.setTypeface(Typeface.DEFAULT_BOLD);w = getFontWidth(paint, str);y = blackFontHeight * 4 + kitchenNameHeight + topBlank + perLineDistance * 4;canvas.drawText(str, 0, y, paint);paint.setTypeface(Typeface.DEFAULT);canvas.drawText("4884977449494949494", w + perFontDistance, y, paint);paint.setTypeface(Typeface.DEFAULT_BOLD);//画线y = y + perLineDistance * 2;canvas.drawLine(0, y, bmpWidth, y, paint);//title(菜品、数量)y = y + perLineDistance * 2;canvas.drawText("菜品", 20, y, paint);canvas.drawText("数量", bmpWidth - getFontWidth(paint, "数量") - 50, y, paint);//画线y = y + blackFontHeight;canvas.drawLine(0, y, bmpWidth, y, paint);//下面是画菜品文本// ArrayList<String> list = new ArrayList<>();// list.add("西兰花胡萝卜蘑菇洋葱虾仁火腿黑豆饭忙伐啦小龙虾还有宫");// list.add("备注:少食、多辣");// list.add("2");paint.setTypeface(Typeface.DEFAULT);y = y + perLineDistance * 2;Log.i("msg", "上面的高度2:" + y);int countStart = bmpWidth - getFontWidth(paint, "数量") - 50;int remarkLeft = getFontWidth(paint, "备注");//备注缩进2个字符的距离for (int i = 0; i < pros.size(); i++) {//先画后面的值,菜品名称最后画,因为菜品名称可能多行显示,要计算最终的高度;// canvas.drawText(list.get(2), countStart, y, paint);canvas.drawText(String.valueOf(pros.get(i).getCount()), countStart, y, paint);//根据菜品文本长度显示多行int lines = getProShowLine(pros.get(i).getProductName());for (int j = 0; j < lines; j++) {str = getSubPro(pros.get(i).getProductName(), j, lines);canvas.drawText(str, 0, y, paint);y = y + normalFontHeight + perLineDistance;}//显示备注lines = getProShowLine(pros.get(i).getChoseLable());for (int j = 0; j < lines; j++) {str = getSubPro("备注: " + pros.get(i).getChoseLable(), j, lines);canvas.drawText(str, remarkLeft, y, paint);y = y + normalFontHeight + perFontDistance;}y = y + perLineDistance;//让备注后下面距离大点}Log.i("msg", "中间的高度2:" + y);str = "总计: ";paint.setTypeface(Typeface.DEFAULT_BOLD);paint.setTextSize(30);w = getFontWidth(paint, str);y = y + 50;canvas.drawText(str, bmpWidth / 2 - w / 2, y, paint);canvas.drawText("8", countStart, y, paint);y = y + bottomBlank;Log.i("msg", "最后的高度2:" + y);return bmp;}/*** 判断菜品需要显示几行** @param dishName* @return*/public static int getProShowLine(String dishName) {int line = 1;//设置每行显示12个字符,超过就换行;if (dishName.length() > 12) {if (dishName.length() % 12 == 0) {line = dishName.length() / 12;} else {line = dishName.length() / 12 + 1;}}return line;}/*** 截取每行需要显示的菜品文本** @param dishName* @param lineIndex* @param lines* @return*/public static String getSubPro(String dishName, int lineIndex, int lines) {String subStr = "";if (lines == 1) {subStr = dishName;} else if (lineIndex != lines - 1 || dishName.length() % 12 == 0) {subStr = dishName.substring(lineIndex * 12, (lineIndex + 1) * 12);} else {subStr = dishName.substring(lineIndex * 12);}return subStr;}}