如何从RecyclerView或Bitmap生成PDF?求新版解决方案
从RecyclerView生成PDF的现代解决方案
首先先优化你提供的RecyclerView截图函数,修复一处冗余的Canvas创建问题:
private fun getRecyclerViewScreenshotAsBitmap( recyclerView: RecyclerView, defaultColor: Int = Color.WHITE ): Bitmap { recyclerView.measure( View.MeasureSpec.makeMeasureSpec(recyclerView.width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) ) val bitmap = Bitmap.createBitmap( recyclerView.width, recyclerView.measuredHeight, Bitmap.Config.ARGB_8888 ) val canvas = Canvas(bitmap) canvas.drawColor(defaultColor) // 复用已创建的Canvas,避免重复实例化 recyclerView.draw(canvas) return bitmap }
方案一:直接将RecyclerView内容绘制到PDF(无需先转Bitmap)
使用Android系统原生的PdfDocument类(属于AndroidX,无需额外依赖),直接将RecyclerView渲染到PDF页面,效率更高:
private fun generatePdfFromRecyclerView(recyclerView: RecyclerView, outputFile: File) { // 先测量RecyclerView总高度 recyclerView.measure( View.MeasureSpec.makeMeasureSpec(recyclerView.width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) ) val rvWidth = recyclerView.measuredWidth val rvHeight = recyclerView.measuredHeight // 获取屏幕密度,用于将px转换为PDF的点单位(1pt = 1/72英寸) val displayMetrics = recyclerView.context.resources.displayMetrics val scale = displayMetrics.densityDpi / 72f // 创建PDF文档 val pdfDocument = PdfDocument() // 创建PDF页面,尺寸对应RecyclerView的实际大小(转换为点) val pageInfo = PdfDocument.PageInfo.Builder( (rvWidth / scale).toInt(), (rvHeight / scale).toInt(), 1 ).create() // 获取页面画布 val page = pdfDocument.startPage(pageInfo) val canvas = page.canvas // 缩放画布,适配PDF的点单位 canvas.scale(1/scale, 1/scale) // 绘制背景色 canvas.drawColor(Color.WHITE) // 将RecyclerView绘制到PDF画布 recyclerView.draw(canvas) // 结束页面并保存PDF pdfDocument.finishPage(page) try { pdfDocument.writeTo(FileOutputStream(outputFile)) } catch (e: IOException) { e.printStackTrace() } finally { pdfDocument.close() } }
方案二:将已生成的Bitmap转换为PDF
如果已经通过你的截图函数得到了Bitmap,可直接将Bitmap绘制到PDF页面:
private fun generatePdfFromBitmap(bitmap: Bitmap, outputFile: File) { val displayMetrics = Resources.getSystem().displayMetrics val scale = displayMetrics.densityDpi / 72f val pdfDocument = PdfDocument() val pageInfo = PdfDocument.PageInfo.Builder( (bitmap.width / scale).toInt(), (bitmap.height / scale).toInt(), 1 ).create() val page = pdfDocument.startPage(pageInfo) val canvas = page.canvas // 缩放画布并绘制Bitmap canvas.scale(1/scale, 1/scale) canvas.drawBitmap(bitmap, 0f, 0f, null) pdfDocument.finishPage(page) try { pdfDocument.writeTo(FileOutputStream(outputFile)) } catch (e: IOException) { e.printStackTrace() } finally { pdfDocument.close() } }
注意事项
- 权限处理:Android 10及以下需要申请
WRITE_EXTERNAL_STORAGE权限;Android 11+推荐使用**存储访问框架(SAF)**让用户选择保存位置,避免权限问题。 - 长列表处理:如果RecyclerView内容超过单页PDF大小,需要拆分内容到多个页面,可通过计算每页高度、滚动RecyclerView分段绘制实现。
内容的提问来源于stack exchange,提问作者burhanyaprak
相关产品推荐
相关产品推荐

