
本文介绍如何将用户输入生成的 RecyclerView 列表(含多个条目)正确渲染为结构清晰、不重叠的 PDF 文档,避免直接调用 canvas.drawText() 导致的布局错位问题,并支持自动分页。
本文介绍如何将用户输入生成的 recyclerview 列表(含多个条目)正确渲染为结构清晰、不重叠的 pdf 文档,避免直接调用 `canvas.drawtext()` 导致的布局错位问题,并支持自动分页。
在 Android 中将 RecyclerView 内容导出为 PDF 时,常见误区是绕过 View 的测量与布局流程,直接使用 Canvas.drawText() 手动定位文本——这会导致所有条目绘制在同一坐标(如 (70, 90)),造成严重重叠。正确做法是复用 RecyclerView 的 ViewHolder 机制:通过 LayoutInflater 创建对应 item 布局的 View 实例,调用 measure() 和 layout() 进行精确尺寸计算与位置排布,再将其内容绘制到 PDF Canvas 上。
以下为关键实现步骤:
✅ 正确渲染流程(核心代码片段)
// 1. 获取 PDF 页面画布(以 PdfDocument.Page 为例)
PdfDocument.Page page = pdfDocument.startPage(new PdfDocument.PageInfo.Builder(595, 842, 1).create());
Canvas canvas = page.getCanvas();
// 2. 复用 item 布局(假设 item_layout.xml 包含 TextView titleView)
View itemView = LayoutInflater.from(context)
.inflate(R.layout.item_layout, null, false);
// 3. 遍历数据,逐项渲染并处理分页
int yPosition = 50; // 当前绘制 Y 坐标(留出页眉)
int pageHeight = 842;
int bottomMargin = 50;
for (int i = 0; i pageHeight - bottomMargin) {
pdfDocument.finishPage(page); // 结束当前页
page = pdfDocument.startPage(new PdfDocument.PageInfo.Builder(595, 842, ++pageNum).create());
canvas = page.getCanvas();
yPosition = 50; // 新页重置起始 Y
}
// 将 View 绘制到 PDF Canvas(平移至目标位置)
itemView.setDrawingCacheEnabled(true);
itemView.buildDrawingCache();
Bitmap bitmap = itemView.getDrawingCache();
canvas.drawBitmap(bitmap, 0, yPosition, null);
yPosition += itemView.getMeasuredHeight() + 20; // 行间距
itemView.destroyDrawingCache();
}
pdfDocument.finishPage(page);
⚠️ 注意事项
-
性能优化:避免在循环中重复
inflate(),建议提前缓存itemView模板或使用ViewPool; -
字体与样式:确保
item_layout.xml中的 TextView 使用系统兼容字体(如sans-serif),避免 PDF 渲染缺失; -
分页健壮性:需考虑标题栏、页脚、页码等固定元素占用空间,建议封装为
PageRenderer类统一管理; -
权限与存储:导出前申请
Manifest.permission.WRITE_EXTERNAL_STORAGE(Android 10+ 推荐使用MediaStore或应用专属目录)。
开源参考项目 RecyclerviewPdf 提供了完整的可运行示例,包含 RecyclerView Adapter 适配、动态分页检测及多类型 ViewHolder 支持,推荐作为工程化落地的基础模板。
最终生成的 PDF 将严格保持原始列表的视觉结构、间距与样式,真正实现「所见即所得」的高质量导出。











