如何通过WiFi/蓝牙打印机打印PDF并适配不同打印机尺寸?
问题:PDF适配不同尺寸打印机的实现方案
我需要通过WiFi或蓝牙打印机打印PDF文件,目前已完成打印机连接,但遇到打印机尺寸小于PDF默认A4页面的问题,导致打印内容被截断、效果异常。现寻求让PDF适配所有尺寸打印机的解决方案,以下是我的Kotlin实现代码、打印效果及打印机信息:
生成PDF的核心代码
private fun savePdf( invoiceType: String, invoiceModel: SalesDatabase, date: String, personType: String, personName: String, paymentMethod: String ) { val am: AssetManager = context.assets var font: PdfFont? try { am.open("text.ttf").use { inStream -> val buffer = ByteArrayOutputStream() var nRead: Int val data = ByteArray(16384) while (inStream.read(data, 0, data.size).also { nRead = it } != -1) { buffer.write(data, 0, nRead) } font = PdfFontFactory.createFont(buffer.toByteArray(), PdfEncodings.UTF8) } } catch (e: Exception) { Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show() return } val mFileName = SimpleDateFormat( "yyyyMMdd_HHmmss", Locale.getDefault() ).format(System.currentTimeMillis()) val mFilePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) .toString() + "/" + "$invoiceType Invoice" + mFileName + ".pdf" val file = File(mFilePath) file.createNewFile() val outputStream: OutputStream = FileOutputStream(file) val pdfWriter = PdfWriter(outputStream) val pdfDocument = PdfDocument(pdfWriter) val mDoc = Document(pdfDocument) try { if (file.exists()) { //Setting mDoc.pdfDocument.defaultPageSize = PageSize.A4 val typeInvoice = "Invoice $invoiceType" val text = Paragraph(typeInvoice).setBold().setFontColor(ColorConstants.BLACK) .setFont(font).setTextAlignment(TextAlignment.CENTER).setFontSize(22f) .setVerticalAlignment(VerticalAlignment.MIDDLE) val textWidth = PageSize.A4.width val table1 = Table(FloatArray(1) { textWidth }) table1.addCell( Cell().add(text) .setBorder(Border.NO_BORDER) .setHorizontalAlignment(HorizontalAlignment.CENTER) .setTextAlignment(TextAlignment.CENTER) .setVerticalAlignment(VerticalAlignment.MIDDLE) ) mDoc.add(table1) addLineSpace(mDoc) val width = PageSize.A4.width / 3 val columns = FloatArray(3) columns[0] = width columns[1] = width columns[2] = width val infoTable = Table(columns) val theDate = Paragraph("Date : $date").setBold().setFont(font) .setFontColor(ColorConstants.BLACK) .setTextAlignment(TextAlignment.CENTER).setFontSize(12f) .setVerticalAlignment(VerticalAlignment.MIDDLE) val theTypeName = Paragraph("$personType Name: $personName").setBold().setFont(font) .setFontColor(ColorConstants.BLACK) .setTextAlignment(TextAlignment.CENTER).setFontSize(12f) .setVerticalAlignment(VerticalAlignment.MIDDLE) val thePaymentType = Paragraph("Payment method : $paymentMethod").setBold().setFont(font) .setFontColor(ColorConstants.BLACK) .setTextAlignment(TextAlignment.CENTER).setFontSize(12f) .setVerticalAlignment(VerticalAlignment.MIDDLE) infoTable.addCell( Cell().add(theDate) .setBorder(Border.NO_BORDER) .setHorizontalAlignment(HorizontalAlignment.CENTER) .setTextAlignment(TextAlignment.CENTER) .setVerticalAlignment(VerticalAlignment.MIDDLE) ) infoTable.addCell( Cell().add(theTypeName) .setBorder(Border.NO_BORDER) .setHorizontalAlignment(HorizontalAlignment.CENTER) .setTextAlignment(TextAlignment.CENTER) .setVerticalAlignment(VerticalAlignment.MIDDLE) ) infoTable.addCell( Cell().add(thePaymentType) .setBorder(Border.NO_BORDER) .setHorizontalAlignment(HorizontalAlignment.CENTER) .setTextAlignment(TextAlignment.CENTER) .setVerticalAlignment(VerticalAlignment.MIDDLE) ) mDoc.add(infoTable) addLineSpace(mDoc) addLineSeparator(mDoc) addLineSpace(mDoc) addTable(mDoc, invoiceModel, font) } mDoc.close() showPleaseWaitDialog(false, "") Toast.makeText(context, "تم إنشاء الملف", Toast.LENGTH_LONG).show() Toast.makeText(context, "تم حفظ الملف في $mFilePath", Toast.LENGTH_LONG).show() Handler().postDelayed({ // val intent = Intent(context, ShowPdf::class.java) // intent.putExtra("pdfUrl", mFilePath) // context.startActivity(intent) printPDF(file) }, 1000) } catch (e: Exception) { Toast.makeText(context, e.message, Toast.LENGTH_LONG).show() } }
打印PDF的代码
private fun printPDF(file: File) { if (OptionDatabase.isWifiMode(context)) { val printManager: PrintManager? = getSystemService(context, PrintManager::class.java) try { val printDocumentAdapter: PrintDocumentAdapter = PdfDocumentAdapter(context, file.path) printManager!!.print( "Document", printDocumentAdapter, PrintAttributes.Builder().build() ) } catch (ex: java.lang.Exception) { Toast.makeText(context, "Can't read pdf file", Toast.LENGTH_SHORT).show() } return } if (OptionDatabase.isBluetoothMode(context)) { Printooth.printer().printingCallback = this Printooth.printer().print(pdfToBitmap(file)) return } }
PDF转Bitmap的代码
private fun pdfToBitmap(pdfFile: File): ArrayList<Printable> { val bitmaps = ArrayList<Printable>() try { val renderer = PdfRenderer( ParcelFileDescriptor.open( pdfFile, ParcelFileDescriptor.MODE_READ_ONLY ) ) var bitmap: Bitmap val pageCount = renderer.pageCount for (i in 0 until pageCount) { val page = renderer.openPage(i) val width: Int = resources.displayMetrics.densityDpi / 72 * page.width val height: Int = resources.displayMetrics.densityDpi / 72 * page.height bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY) bitmaps.add(ImagePrintable.Builder(bitmap).build()) // close the page page.close() } // close the renderer renderer.close() } catch (ex: java.lang.Exception) { context.showToast(ex.message.toString(), 0) } return bitmaps }
添加表格的代码
private fun addTable(document: Document, invoiceModel: PurchaseDatabase, font: PdfFont?) { val columns = FloatArray(5) columns[0] = 30f columns[1] = (PageSize.A4.width - 30f) / 4 columns[2] = (PageSize.A4.width - 30f) / 4 columns[3] = (PageSize.A4.width - 30f) / 4 columns[4] = (PageSize.A4.width - 30f) / 4 val table = Table(columns).setMarginBottom(20f) addCell(table, "", font!!, true) addCell(table, "Product Name", font, true) addCell(table, "Price", font, true) addCell(table, "Quantity", font, true) addCell(table, "Total", font, true) val myType = object : TypeToken<ArrayList<ProductBuyModel>>() {}.type val products = Gson().fromJson<ArrayList<ProductBuyModel>>(invoiceModel.products, myType) for (s in products.indices) { addCell(table, (s + 1).toString(), font, false) addCell(table, products[s].productName, font, false) val price = (products[s].productPrixTotal - products[s].productTax) / products[s].productQuantity addCell(table, price.toString(), font, false) addCell(table, products[s].productQuantity.toString(), font, false) addCell(table, products[s].productPrixTotal.toString(), font, false) } addCell(table, "", font, false) addCell(table, "", font, false) addCell(table, "Payment : ${invoiceModel.paymentPrice}", font, true) addCell(table, "Rest : ${invoiceModel.restPrice}", font, true) addCell(table, "Total : ${invoiceModel.totalPrice}", font, true) table.setBackgroundColor(ColorConstants.WHITE) table.isKeepTogether = true document.add(table) }
打印效果与打印机信息
- 打印效果:PDF内容因打印机尺寸小于A4,右侧内容被截断,无法完整显示。
- 打印机信息:打印机为热敏小票打印机,支持的纸张宽度为80mm(约3.15英寸),远小于A4的210mm宽度。
内容的提问来源于stack exchange,提问作者Bakir Lakaf
相关产品推荐
相关产品推荐

