一、PdfDocument使用
PdfDocument是Android原生的生成pdf文件的类,这个类的使用可参考:
https://developer.android.google.cn/reference/kotlin/android/graphics/pdf/PdfDocument
https://blog.csdn.net/tangedegushi/article/details/81502394
二、问题及解决
背景:需要动态加载一个View,View里面的内容也是动态添加的(比如动态添加多个TextView)。将View的内容生成Pdf文件。
问题: 生成的pdf是空白的?
解决:发现直接添加在布局文件里的内容可以在生成的PDF文件中显示,而动态添加的显示不出来。查找资料发现
https://blog.csdn.net/weixin_40022240/article/details/80692596,应该是因为动态生成的View没有进行Measure 和Layout 所以没有绘制出来,添加上果然就可以了,问题解决。
实例:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="800dp"
android:layout_height="1200dp">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll_ecg_pdf"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"></LinearLayout>
</ScrollView>
</LinearLayout>
代码: 根据数据向LinearLayout内动态添加绘制了心电图的View,之后将View生成pdf文件
public void generatePdf(String historyTime){
String pdfFilePath = BASE_PATH + File.separator + historyTime+".pdf";
File pdfFile = new File(pdfFilePath);
File baseFile = new File(BASE_PATH);
if(!baseFile.exists()) {
baseFile.mkdir();
}
if(pdfFile.exists()){
pdfFile.delete();
}
int onePageHeight = Utils.dip2px(mContext, 250)*2; //每页高度
int pdfCount = 2; //总页数
PdfDocument document = new PdfDocument();//1, 建立PdfDocument
/* 生成单页
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo
.Builder(1080, onePageHeight, 1)
// .setContentRect(new Rect(0,60,1080,onePageHeight+60))
.create();//2 crate a page description
PdfDocument.Page page = document.startPage(pageInfo); //3、start a page
Canvas canvas = page.getCanvas();
Log.d("ttt","the mLlEcgPdf width:"+mLlEcgPdf.getWidth()+ "; height:"+mLlEcgPdf.getHeight());
measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), //2, 测量大小
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
layout(0, 0,mLlEcgPdf.getMeasuredWidth(), mLlEcgPdf.getMeasuredHeight()); //3, 测量位置
draw(canvas);
document.finishPage(page);///5、finish the page
*/
//生成多页的pdf
for (int i = 0; i < pdfCount; i++) {
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo
.Builder(1080, onePageHeight, pdfCount)
// .setContentRect(new Rect(0,60,mLlEcgPdf.getWidth(),onePageHeight+60))
.create();//2 crate a page description
PdfDocument.Page page = document.startPage(pageInfo); //3、start a page
Canvas canvas = page.getCanvas();
canvas.translate(0,-onePageHeight*i);
measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), // 测量大小
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
layout(0, 0,mLlEcgPdf.getMeasuredWidth(), mLlEcgPdf.getMeasuredHeight()); // 测量位置
mLlEcgPdf.draw(canvas);//4、 draw something on the page
document.finishPage(page);///5、finish the page
}
try {
document.writeTo(new FileOutputStream(pdfFile)); //write the document content
// Toast.makeText(ECGActivity.this,"文件已生成,存储路径:"+BASE_PATH ,Toast.LENGTH_SHORT).show();
AlertDialog dialog = new AlertDialog.Builder(mContext).setTitle("").setMessage("文件已生成,存储路径:"+BASE_PATH).create();
dialog.show();
} catch (IOException e) {
e.printStackTrace();
}
document.close(); //close the document
}
重点就是添加
measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), //2, 测量大小
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
layout(0, 0,mLlEcgPdf.getMeasuredWidth(), mLlEcgPdf.getMeasuredHeight()); //3, 测量位置
mLlEcgPdf.draw(canvas);
通过测量measure,布局layout,绘制draw,将动态添加的View绘制出来,注意这里的MeasureSpec是unspecified, 我们的pdfview并没有一个父控件,随意高宽不必受约束,layout也是确定子控件的位置。没有上面代码将导致生成的Pdf 空白。
其中生成多页的Pdf文件参考:
https://blog.csdn.net/MikoGodZd/article/details/51767848