Android 生成pdf文件

爱被打了一巴掌 2024-03-17 19:33 230阅读 0赞

Android 生成pdf文件

1.使用官方的方式

使用官方的方式也就是PdfDocument类的使用

1.1 基本使用

  1. /***
  2. * 将tv内容写入到pdf文件
  3. */
  4. @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  5. private void newPdf() {
  6. // 创建一个PDF文本对象
  7. PdfDocument document = new PdfDocument();
  8. //创建当前页的信息,Builder中的参数表示页面的宽高,以及第几页
  9. PdfDocument.PageInfo pageInfo =
  10. new PdfDocument.PageInfo.Builder(binding.pdfTv.getWidth(), binding.pdfTv.getHeight(), 1)
  11. .create();
  12. // 生成当前页
  13. PdfDocument.Page page = document.startPage(pageInfo);
  14. // 在当前页上画画,即把所需要的view的视图画到page的画布上
  15. View content = pdfTv;
  16. content.draw(page.getCanvas());
  17. // 结束当前页
  18. document.finishPage(page);
  19. String filePath = getExternalFilesDir("").getAbsolutePath() + "/test.pdf";
  20. try {
  21. FileOutputStream outputStream = new FileOutputStream(new File(filePath));
  22. //写入到文件中
  23. document.writeTo(outputStream);
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. }
  27. //关闭
  28. document.close();
  29. }

注意事项

1.需要申请写入文件的权限

2.API最低是19,有api版本的限制

1.2 将根布局的内容生成pdf文件

  1. /***
  2. * 保存一个屏幕的内容(包含界面中的 文字、图片、按钮等)
  3. */
  4. @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  5. private void pdfTvAndIv() {
  6. // 创建一个PDF文本对象
  7. PdfDocument document = new PdfDocument();
  8. //创建当前页的信息,Builder中的参数表示页面的宽高,以及第几页
  9. PdfDocument.PageInfo pageInfo =
  10. new PdfDocument.PageInfo.Builder(binding.getRoot().getWidth(), binding.getRoot().getHeight(), 1)
  11. .create();
  12. // 生成当前页
  13. PdfDocument.Page page = document.startPage(pageInfo);
  14. // 在当前页上画画,即把所需要的view的视图画到page的画布上
  15. View content = binding.getRoot();
  16. content.draw(page.getCanvas());
  17. // 结束当前页
  18. document.finishPage(page);
  19. String filePath = getExternalFilesDir("").getAbsolutePath() + "/tviv.pdf";
  20. try {
  21. FileOutputStream outputStream = new FileOutputStream(new File(filePath));
  22. document.writeTo(outputStream);
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. }
  26. document.close();
  27. }

也同样简单。binding.getRoot()就是xml文件的根布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <layout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools">
  4. <data>
  5. </data>
  6. <ScrollView
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:orientation="vertical"
  10. tools:context=".pdf.PdfActivity">
  11. <LinearLayout
  12. android:layout_width="match_parent"
  13. android:layout_height="match_parent"
  14. android:orientation="vertical">
  15. <TextView
  16. android:id="@+id/pdf_tv"
  17. android:layout_width="match_parent"
  18. android:layout_height="wrap_content"
  19. android:text="" />
  20. <ImageView
  21. android:id="@+id/pdf_iv"
  22. android:layout_width="wrap_content"
  23. android:layout_height="wrap_content"
  24. android:scaleType="fitXY"
  25. android:src="@mipmap/logo"
  26. android:visibility="visible" />
  27. <Button
  28. android:id="@+id/pdf1"
  29. android:layout_width="match_parent"
  30. android:layout_height="wrap_content"
  31. android:text="官方方式生成pdf" />
  32. </LinearLayout>
  33. </ScrollView>
  34. </layout>

1.3 TextView有很多行,超过一屏

  1. /***
  2. * 将多行的文字写入到pdf文件
  3. */
  4. @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  5. private void pdfInterviewContent() {
  6. TextView tv_content = binding.pdfTv;
  7. // 创建一个PDF文本对象
  8. PdfDocument document = new PdfDocument();
  9. // 一页pdf的高度
  10. int onePageHeight = tv_content.getLineHeight() * 30;
  11. // TextView中总共有多少行
  12. int lineCount = tv_content.getLineCount();
  13. // 计算这个TextView需要分成多少页
  14. int pdfCount = lineCount % 30 == 0 ? lineCount / 30 : lineCount / 30 + 1;
  15. for (int i = 0; i < pdfCount; i++) {
  16. PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(tv_content.getWidth(), onePageHeight + 120, 1)
  17. .setContentRect(new Rect(0, 60, tv_content.getWidth(), onePageHeight + 60))
  18. .create();
  19. PdfDocument.Page page = document.startPage(pageInfo);
  20. Canvas canvas = page.getCanvas();
  21. canvas.translate(0, -onePageHeight * i);
  22. tv_content.draw(canvas);
  23. document.finishPage(page);
  24. }
  25. //document = pdfImageviewContent(document);
  26. File file = new File(getExternalFilesDir("").getAbsolutePath() + "/test.pdf");
  27. try {
  28. FileOutputStream outputStream = new FileOutputStream(file);
  29. document.writeTo(outputStream);
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. document.close();
  34. }

1.4 小结

  1. 1.保存的文件有些大
  2. 2.保存超过一屏的内容有些难,涉及到canvas的移动
  3. 3.同时保存文字与图片有些难度(如果超过一屏幕的话,图片保存后会是空白的情况。没有超过一屏,保存后能正常显示)
  4. 4.如果界面中有特殊的view,可能会保存失败!比如说SurfaceView
  5. [附上解决方案的链接](https://www.jianshu.com/p/1ebaf5e6fac1)

2.使用itext的方式

对于Itext,主要有两个版本,一个是5.x,另一个是7.x,这两个版本是完全是不兼容的,其区别可以参考官网:iText 7 and iText 5: roadmaps, differences, updates | iText PDF,

5.x的文档:iText Javadoc Home

7.x的文档:iText Javadoc Home

2.1 7.x

一、引入依赖
  1. //iText 7.0+
  2. implementation 'com.itextpdf:itext7-core:7.1.13'

目前使用的Android Studio版本是4.0.1,我使用的是jdk1.8,不能引入最新的7.1.15版本,会报错

  1. Unsupported class file major version 59

这个问题对jdk有要求的。

二、申请权限

清单文件AndroidManifest.xml

2.1 申请权限

2.2 在中添加

android:requestLegacyExternalStorage=”true”

2.3 添加provider



2.4 在res目录下新建xml目录,并创建provider_paths.xml文件

<?xml version=”1.0” encoding=”utf-8”?>



三、创建pdf文件
  1. /**
  2. * 创建PDF文件
  3. */
  4. private void createPDF(String path) {
  5. if (XXPermissions.isGranted(TextActivity.this, Permission.MANAGE_EXTERNAL_STORAGE)) {
  6. File file = new File(path);
  7. if (file.exists()) {
  8. file.delete();
  9. }
  10. file.getParentFile().mkdirs();
  11. // 创建Document
  12. PdfWriter writer = null;
  13. try {
  14. writer = new PdfWriter(new FileOutputStream(path));
  15. } catch (FileNotFoundException e) {
  16. Log.e("FileNotFoundException", e.toString());
  17. }
  18. PdfDocument pdf_document = new PdfDocument(writer);
  19. // 生成的PDF文档信息
  20. PdfDocumentInfo info = pdf_document.getDocumentInfo();
  21. // 标题
  22. info.setTitle("First pdf file");
  23. // 作者
  24. info.setAuthor("Quinto");
  25. // 科目
  26. info.setSubject("test");
  27. // 关键词
  28. info.setKeywords("pdf");
  29. // 创建日期
  30. info.setCreator("2022-10-20");
  31. Document document = new Document(pdf_document, PageSize.A4, false);
  32. // 文字字体(显示中文)、大小、颜色
  33. PdfFont font = null;
  34. try {
  35. font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
  36. } catch (IOException e) {
  37. Log.e("IOException", e.toString());
  38. }
  39. float title_size = 36.0f;
  40. float text_title_size = 30.0f;
  41. float text_size = 24.0f;
  42. Color title_color = new DeviceRgb(0, 0, 0);
  43. Color text_title_color = new DeviceRgb(65, 136, 160);
  44. Color text_color = new DeviceRgb(43, 43, 43);
  45. // 行分隔符
  46. // 实线:SolidLine() 点线:DottedLine() 仪表盘线:DashedLine()
  47. LineSeparator separator = new LineSeparator(new SolidLine());
  48. separator.setStrokeColor(new DeviceRgb(0, 0, 68));
  49. // 添加大标题
  50. Text title = new Text("这里是pdf文件标题").setFont(font).setFontSize(title_size).setFontColor(title_color);
  51. Paragraph paragraph_title = new Paragraph(title).setTextAlignment(TextAlignment.CENTER);
  52. document.add(paragraph_title);
  53. for (int i = 1; i < 10; i++) {
  54. // 添加文本小标题
  55. Text text_title = new Text("第" + i + "行:").setFont(font).setFontSize(text_title_size).setFontColor(text_title_color);
  56. Paragraph paragraph_text_title = new Paragraph(text_title);
  57. document.add(paragraph_text_title);
  58. // 添加文本内容
  59. String content = "我是文本内容" + i + i + i + i + i + i + i + i + i + i;
  60. Text text = new Text(content).setFont(font).setFontSize(text_size).setFontColor(text_color);
  61. Paragraph paragraph_text = new Paragraph(text);
  62. document.add(paragraph_text);
  63. // 添加可换行空间
  64. document.add(new Paragraph(""));
  65. // 添加水平线
  66. document.add(separator);
  67. // 添加可换行空间
  68. document.add(new Paragraph(""));
  69. }
  70. /**
  71. * 添加列表
  72. */
  73. List list = new List().setSymbolIndent(12).setListSymbol("\u2022").setFont(font);
  74. list.add(new ListItem("列表1"))
  75. .add(new ListItem("列表2"))
  76. .add(new ListItem("列表3"));
  77. document.add(list);
  78. /**
  79. * 添加图片
  80. */
  81. Text text_image = new Text("图片:").setFont(font).setFontSize(text_title_size).setFontColor(text_title_color);
  82. Paragraph image = new Paragraph(text_image);
  83. document.add(image);
  84. Image image1 = null;
  85. Image image2 = null;
  86. Image image3 = null;
  87. try {
  88. /*image1 = new Image(ImageDataFactory.create("/storage/emulated/0/DCIM/Camera/IMG_20221003_181926.jpg")).setWidth(PageSize.A4.getWidth() * 2 / 3);
  89. image2 = new Image(ImageDataFactory.create("/storage/emulated/0/Download/互传/folder/证件/XHS_159716343059020494b83-da6a-39d7-ae3b-13fd92cfbb53.jpg")).setWidth(PageSize.A4.getWidth() / 3);
  90. image3 = new Image(ImageDataFactory.create("/storage/emulated/0/Download/互传/folder/证件/XHS_1597163520524f0b4df77-8db1-35c6-9dfa-3e0aa74f1fef.jpg")).setWidth(PageSize.A4.getWidth() / 3);*/
  91. image1 = new Image(ImageDataFactory.create("/storage/emulated/0/Pictures/JPEG_20230609_154240_8941441911022988116.jpg")).setWidth(PageSize.A4.getWidth() * 2 / 3);
  92. image2 = new Image(ImageDataFactory.create("/storage/emulated/0/Tencent/QQ_Images/-318f738d395e5630.jpg")).setWidth(PageSize.A4.getWidth() / 3);
  93. image3 = new Image(ImageDataFactory.create("/storage/emulated/0/Pictures/Screenshots/Screenshot_20230615_145522_com.hermes.wl.jpg")).setWidth(PageSize.A4.getWidth() / 3);
  94. } catch (MalformedURLException e) {
  95. Log.e("MalformedURLException", e.toString());
  96. }
  97. Paragraph paragraph_image = new Paragraph().add(image1)
  98. .add(" ")
  99. .add(image2)
  100. .add(" ")
  101. .add(image3);
  102. document.add(paragraph_image);
  103. document.add(new Paragraph(""));
  104. /**
  105. * 添加表格
  106. */
  107. Text text_table = new Text("表单:").setFont(font).setFontSize(text_title_size).setFontColor(text_title_color);
  108. Paragraph paragraph_table = new Paragraph(text_table);
  109. document.add(paragraph_table);
  110. // 3列
  111. float[] pointColumnWidths = {100f, 100f, 100f};
  112. Table table = new Table(pointColumnWidths);
  113. // 设置边框样式、颜色、宽度
  114. Color table_color = new DeviceRgb(80, 136, 255);
  115. Border border = new DottedBorder(table_color, 3);
  116. table.setBorder(border);
  117. // 设置单元格文本居中
  118. table.setTextAlignment(TextAlignment.CENTER);
  119. // 添加单元格内容
  120. Color table_header = new DeviceRgb(0, 0, 255);
  121. Color table_content = new DeviceRgb(255, 0, 0);
  122. Color table_footer = new DeviceRgb(0, 255, 0);
  123. Text text1 = new Text("姓名").setFont(font).setFontSize(20.0f).setFontColor(table_header);
  124. Text text2 = new Text("年龄").setFont(font).setFontSize(20.0f).setFontColor(table_header);
  125. Text text3 = new Text("性别").setFont(font).setFontSize(20.0f).setFontColor(table_header);
  126. table.addHeaderCell(new Paragraph(text1));
  127. table.addHeaderCell(new Paragraph(text2));
  128. table.addHeaderCell(new Paragraph(text3));
  129. Text text4 = new Text("张三").setFont(font).setFontSize(15.0f).setFontColor(table_content);
  130. Text text5 = new Text("30").setFont(font).setFontSize(15.0f).setFontColor(table_content);
  131. Text text6 = new Text("男").setFont(font).setFontSize(15.0f).setFontColor(table_content);
  132. table.addCell(new Paragraph(text4));
  133. table.addCell(new Paragraph(text5));
  134. table.addCell(new Paragraph(text6));
  135. Text text7 = new Text("丽萨").setFont(font).setFontSize(15.0f).setFontColor(table_footer);
  136. Text text8 = new Text("20").setFont(font).setFontSize(15.0f).setFontColor(table_footer);
  137. Text text9 = new Text("女").setFont(font).setFontSize(15.0f).setFontColor(table_footer);
  138. table.addFooterCell(new Paragraph(text7));
  139. table.addFooterCell(new Paragraph(text8));
  140. table.addFooterCell(new Paragraph(text9));
  141. // 将表格添加进pdf文件
  142. document.add(table);
  143. /**
  144. * 添加页眉、页脚、水印
  145. */
  146. Rectangle pageSize;
  147. PdfCanvas canvas;
  148. int n = pdf_document.getNumberOfPages();
  149. Log.i("zxd", "createPDF: " + n);
  150. for (int i = 1; i <= n; i++) {
  151. PdfPage page = pdf_document.getPage(i);
  152. Log.i("zxd", "createPDF page: " + page.getPageSize());
  153. pageSize = page.getPageSize();
  154. canvas = new PdfCanvas(page);
  155. // 页眉
  156. canvas.beginText().setFontAndSize(font, 7)
  157. .moveText(pageSize.getWidth() / 2 - 18, pageSize.getHeight() - 10)
  158. .showText("我是页眉")
  159. .endText();
  160. // 页脚
  161. canvas.setStrokeColor(text_color)
  162. .setLineWidth(.2f)
  163. .moveTo(pageSize.getWidth() / 2 - 30, 20)
  164. .lineTo(pageSize.getWidth() / 2 + 30, 20).stroke();
  165. canvas.beginText().setFontAndSize(font, 7)
  166. .moveText(pageSize.getWidth() / 2 - 6, 10)
  167. .showText(String.valueOf(i))
  168. .endText();
  169. // 水印
  170. Paragraph p = new Paragraph("Quinto").setFontSize(60);
  171. canvas.saveState();
  172. PdfExtGState gs1 = new PdfExtGState().setFillOpacity(0.2f);
  173. canvas.setExtGState(gs1);
  174. document.showTextAligned(p, pageSize.getWidth() / 2, pageSize.getHeight() / 2,
  175. pdf_document.getPageNumber(page),
  176. TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
  177. canvas.restoreState();
  178. }
  179. // 关闭
  180. document.close();
  181. Toast.makeText(this, "PDF文件已生成", Toast.LENGTH_SHORT).show();
  182. } else {
  183. //没权限
  184. //requestPermission();
  185. }
  186. }

注意事项

1.pdfdocument.getPageSize()未设置为对象iText7的实例,获取页面大小的时候竟然报错,原因是立即刷新的参数设置成true了

可以告诉文档在默认情况下不要刷新其内容,方法是将false传递给构造函数中的第三个参数(immediateflush)

  1. Document document = new Document(pdf_document, PageSize.A4, false);

pdfdocument.getPageSize()未设置为对象iText7的实例

2.如果图片资源没找到,会报io错误。最好在使用前,先判断下图片是否存在!

3.参考:Android使用iText7生成PDF文件

2.2 7.x的基础使用

2.2.1 显示中文

itext7在使用默认字体显示中文的时候,由于默认字库不支持中文,生成的pdf中的中文会显示空白,要解决这个问题需要自己引入字体。

1.下载一个中文的字体(.ttf文件,SourceHanSansCN.ttf)

2.加载本地字体样式

  1. //InputStream inputStream = new FileInputStream(new File("SourceHanSansCN.ttf"));
  2. //第三个参数为embedded,是否为内置字体,这里是自己提供的所以传false
  3. //PdfFont font = PdfFontFactory.createFont(IOUtils.toByteArray(inputStream), PdfEncodings.IDENTITY_H, false);
  4. //Android 一般都是从资产文件获取字体,然后使用字体的byte[]创建禹卫硬笔字体
  5. try {
  6. InputStream open = getAssets().open("禹卫硬笔.ttf");
  7. byte[] datas = new byte[open.available()];
  8. open.read(datas);
  9. font = PdfFontFactory.createFont(datas, PdfEncodings.IDENTITY_H, false);
  10. } catch (IOException e) {
  11. Log.e("IOException", e.toString());
  12. }

3.设置字体

  1. //默认是A4纸大小
  2. Document document = new Document(pdfDocument, new PageSize());
  3. document.setFont(font);
2.2.2 分辨率

如果有pdf打印的需求,涉及到分辨率的问题。

在itext中除了插入的图片外其他都是矢量图所以不必担心分辨率的问题,只需要保证插入图片的分辨率即可,在itext中生成图片的分辨率默认是72dpi,这里是需要做一些处理的,如下:

  1. int defaultDpi = 72;
  2. int targetDpi = 300;
  3. Image test = new Image(ImageDataFactory.create("test.jpg"));
  4. test.scale(defaultDpi/targetDpi, defaultDpi/targetDpi);
2.2.3 布局

Itext坐标系如下图,当使用绝对布局的时候需要计算元素距离左侧和下侧的长度,当使用相对布局的时候,元素则是自上往下排列。

坐标原点图

绝对布局
  1. setFixedPosition(float left, float bottom, float width)
相对布局

使用相对布局时,不需要setFixedPosition,只需要设置距离上下左右的长度即可。

  1. setMarginLeft(float value);
  2. setMarginRight(float value);
  3. setMarginBottom(float value);
  4. setMarginTop(float value);
  5. setMargin(float commonMargin);
2.2.4 自动分页+生成页码
  1. 在使用绝对布局的时候,大部分情况下页面内容是固定大小的,位置也是固定的,分页也需要自己写代码来进行控制。但是如果pdf的内容不是固定的,这时候如果使用绝对布局就不是那么的灵活了,还需要自己计算元素的高度也设置绝对位置,这个时候我们选择使用相对布局则会更合适、简单一些。代码如下:
  2. class PageEventHandler implements IEventHandler {
  3. private Document document;
  4. private PdfFont font;
  5. //由于需要统一和汉字的字体,所以加了一个pdffont参数,没有此需求的可以不加
  6. public PageEventHandler(Document document, PdfFont font){
  7. this.document = document;
  8. this.font = font;
  9. }
  10. @Override
  11. public void handleEvent(Event event) {
  12. PdfDocumentEvent pdfEvent = (PdfDocumentEvent) event;
  13. PdfPage page = pdfEvent.getPage();
  14. PdfDocument pdfDoc = pdfEvent.getDocument();
  15. //获取当前页码
  16. int pageNumber = pdfDoc.getPageNumber(page);
  17. PdfCanvas pdfCanvas = new PdfCanvas(
  18. page.newContentStreamBefore(), page.getResources(), pdfDoc);
  19. //在距离上个元素50的距离处写页码
  20. this.document.setTopMargin(50f);
  21. pdfCanvas.beginText()
  22. .setFontAndSize(this.font, 32)
  23. //在页面一般宽的地方写上当前页面,由于字体定位的原点也在左下角,所以这里x轴减掉了页码宽度的一半,确保页码是写在中间的位置
  24. //y轴是距离底部20px
  25. .moveText(PageSize.A4.getWidth()/2-32/2, 20f)
  26. .showText(String.valueOf(pageNumber))
  27. .endText();
  28. pdfCanvas.release();
  29. }
  30. }
  31. //使用
  32. pdfDocument.addEventHandler(PdfDocumentEvent.START_PAGE, new PageEventHandler(document, font));
2.2.5 常用组件
table
  1. //不指定table每一列的宽度,根据列的内容自适应
  2. public Table(int numColumns);
  3. //指定每一列的宽度
  4. public Table(float[] pointColumnWidths);
  5. //向table里面添加单元格,默认是横着加,达到指定列数后,自动换行
  6. public Table addCell(Cell cell);
  7. //设置table或cell的边框,这里需要注意,如果不想显示边框,需要在每一个cell中都设置border为none,只设置table的边框还是会显示边框的
  8. public T setBorder(Border border);
  9. //无边框
  10. cell.setBorder(Border.NO_BORDER);
  11. //实线边框
  12. cell.setBorder(new SolidBorder(1));
  13. //虚线边框
  14. cell.setBorder(new DashedBorder(1));
  15. //四个都是圆角
  16. cell.setBorderRadius(new BorderRadius(10f));
  17. //圆角-右下角
  18. cell.setBorderBottomRightRadius(new BorderRadius(10f));
  19. //圆角-左下角
  20. cell.setBorderBottomLeftRadius(new BorderRadius(10f));
  21. //圆角-右上角
  22. cell.setBorderTopRightRadius(new BorderRadius(10f));
  23. //圆角-左上角
  24. cell.setBorderTopLeftRadius(new BorderRadius(10f));
  25. //关于圆角这一部分,table中的圆角,似乎设置了并不能生效,不过可以通过将外围的table的border设置为none,内部的cell设置边框实现
用table实现一个进度条
  • 思路:外层一个一行一列的table,内部cell再套一个一行一列的table作为实际的进度,根据百分比计算内部table的宽度

    //percent这里传的是小数
    public void processBar(Document document, float width, float percent){

    1. float processWidth = width * percent;
    2. DeviceRgb processColor = new DeviceRgb(11,11,11);//随便写个颜色吧
    3. DeviceRgb processBgColor = new DeviceRgb(101,11,11);//随便写个颜色吧
    4. Table table = new Table(new float[]{width}).setMargin(0).setPadding(0);//把不必要的空隙都扼杀在摇篮里
    5. Table processTable = new Table(new float[]{processWidth}).setMargin(0).setPadding(0);
    6. processTable.addCell(new Cell().setBorder(Border.NO_BORDER)
    7. .setMargin(0).setPadding(0).setBackgroundColor(processColor));
    8. table.addCell(new Cell().setBorder(Border.NO_BORDER).setBackgroundColor(processBgColor)
    9. .setMargin(0).setPadding(0).setBorder(Border.NO_BORDER).add(processTable));


    }

Paragraph

paragraph应该是最经常使用的一个类了,pdf中写文字都会用到这个类。

  1. Paragraph para = new Paragraph("我是一个paragraph")
  2. .setFontSize(14)//设置字体大小
  3. .setBold()//设置文字为粗体
  4. .setFontColor(new DeviceRgb(0,0,0))//设置字体颜色
  5. .setTextAlignment(TextAlignment.CENTER)//文字水平居中
  6. .setFixedLeading(14);//类似于css中的行高

有的时候会有一些需求是,同一段落的一段文字中有部分文字需要设置成别的颜色或样式样式,这时候可以Text来处理,如下:

  1. //这种处理方式不能处理加粗的问题,如果想要加粗的文字正好在段落的中间,但是如果设置为粗体会导致整段文字都变成粗体(斜体是同理的)
  2. para.add(new Text("我想与众不同").setFontSize("20").setFontColor(new DeviceRgb(255,255,255)));
Image
  1. //图片分辨率问题见上面分辨率部分
  2. Image image = new Image(ImageDataFactory.create("/home/test.jpg"));

参考:Itext7生成pdf最全api总结

2.2.6 基本使用
  1. private void pdf1() {
  2. path = getExternalFilesDir("").getAbsolutePath() + "/itext_basic.pdf";
  3. PdfWriter writer;//创建一个写入传递的输出流的 PdfWriter。
  4. try {
  5. writer = new PdfWriter(new FileOutputStream(path));
  6. PdfFont font = PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN);
  7. PdfDocument pdf = new PdfDocument(writer);
  8. Document document = new Document(pdf);
  9. Text text = new Text("Hello World PDF created using iText")
  10. .setFont(font)
  11. .setFontSize(15)
  12. .setFontColor(ColorConstants.MAGENTA);
  13. //Add paragraph to the document
  14. document.add(new Paragraph(text));
  15. document.close();
  16. } catch (IOException e) {
  17. // TODO Auto-generated catch block
  18. e.printStackTrace();
  19. }
  20. }
2.2.7 字体样式
  1. try {
  2. PdfDocument pdf = new PdfDocument(new PdfWriter(path));
  3. PdfFont font = PdfFontFactory.createFont(StandardFonts.COURIER);
  4. Style style = new Style().setFont(font)
  5. .setFontSize(14)
  6. .setFontColor(ColorConstants.RED)
  7. .setBackgroundColor(ColorConstants.YELLOW);
  8. Document document = new Document(pdf);
  9. document.add(new Paragraph()
  10. .add("In this PDF, ")
  11. .add(new Text("Text is styled").addStyle(style))
  12. .add(" using iText ")
  13. .add(new Text("Style").addStyle(style))
  14. .add("."));
  15. document.close();
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. }
2.2.8 txt转pdf
  1. private void pdf3(String source, String des) {
  2. try {
  3. BufferedReader br = new BufferedReader(new FileReader(source));
  4. PdfDocument pdf = new PdfDocument(new PdfWriter(des));
  5. Document document = new Document(pdf);
  6. String line;
  7. PdfFont font = PdfFontFactory.createFont(StandardFonts.COURIER);
  8. while ((line = br.readLine()) != null) {
  9. document.add(new Paragraph(line).setFont(font));
  10. }
  11. br.close();
  12. document.close();
  13. } catch (IOException e) {
  14. // TODO Auto-generated catch block
  15. e.printStackTrace();
  16. }
  17. }

参考:使用 iText 7在 Java 中生成中文PDF

2.3 打开pdf

  1. /**
  2. * 打开PDF文件
  3. */
  4. private void openPDF() {
  5. new Handler().postDelayed(new Runnable() {
  6. @Override
  7. public void run() {
  8. try {
  9. FileUtils.openFile(context, new File(path));
  10. } catch (Exception e) {
  11. Log.e("Exception", e.toString());
  12. }
  13. }
  14. }, 1000);
  15. }

打开PDF文件

  1. /**
  2. * 打开PDF文件
  3. *
  4. * @param context
  5. * @param url
  6. * @throws ActivityNotFoundException
  7. * @throws IOException
  8. */
  9. public static void openFile(Context context, File url) throws ActivityNotFoundException {
  10. if (url.exists()) {
  11. Uri uri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileprovider", url);
  12. String urlString = url.toString().toLowerCase();
  13. Intent intent = new Intent(Intent.ACTION_VIEW);
  14. intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  15. /**
  16. * Security
  17. */
  18. List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
  19. for (ResolveInfo resolveInfo : resInfoList) {
  20. String packageName = resolveInfo.activityInfo.packageName;
  21. context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
  22. }
  23. // 通过比较url和扩展名,检查您要打开的文件类型。
  24. // 当if条件匹配时,插件设置正确的意图(mime)类型
  25. // 所以Android知道用什么程序打开文件
  26. if (urlString.toLowerCase().contains(".doc")
  27. || urlString.toLowerCase().contains(".docx")) {
  28. // Word document
  29. intent.setDataAndType(uri, "application/msword");
  30. } else if (urlString.toLowerCase().contains(".pdf")) {
  31. // PDF file
  32. intent.setDataAndType(uri, "application/pdf");
  33. } else if (urlString.toLowerCase().contains(".ppt")
  34. || urlString.toLowerCase().contains(".pptx")) {
  35. // Powerpoint file
  36. intent.setDataAndType(uri, "application/vnd.ms-powerpoint");
  37. } else if (urlString.toLowerCase().contains(".xls")
  38. || urlString.toLowerCase().contains(".xlsx")) {
  39. // Excel file
  40. intent.setDataAndType(uri, "application/vnd.ms-excel");
  41. } else if (urlString.toLowerCase().contains(".zip")
  42. || urlString.toLowerCase().contains(".rar")) {
  43. // ZIP file
  44. intent.setDataAndType(uri, "application/trap");
  45. } else if (urlString.toLowerCase().contains(".rtf")) {
  46. // RTF file
  47. intent.setDataAndType(uri, "application/rtf");
  48. } else if (urlString.toLowerCase().contains(".wav")
  49. || urlString.toLowerCase().contains(".mp3")) {
  50. // WAV/MP3 audio file
  51. intent.setDataAndType(uri, "audio/*");
  52. } else if (urlString.toLowerCase().contains(".gif")) {
  53. // GIF file
  54. intent.setDataAndType(uri, "image/gif");
  55. } else if (urlString.toLowerCase().contains(".jpg")
  56. || urlString.toLowerCase().contains(".jpeg")
  57. || urlString.toLowerCase().contains(".png")) {
  58. // JPG file
  59. intent.setDataAndType(uri, "image/jpeg");
  60. } else if (urlString.toLowerCase().contains(".txt")) {
  61. // Text file
  62. intent.setDataAndType(uri, "text/plain");
  63. } else if (urlString.toLowerCase().contains(".3gp")
  64. || urlString.toLowerCase().contains(".mpg")
  65. || urlString.toLowerCase().contains(".mpeg")
  66. || urlString.toLowerCase().contains(".mpe")
  67. || urlString.toLowerCase().contains(".mp4")
  68. || urlString.toLowerCase().contains(".avi")) {
  69. // Video files
  70. intent.setDataAndType(uri, "video/*");
  71. } else {
  72. // 如果你愿意,你也可以为任何其他文件定义意图类型
  73. // 另外,使用下面的else子句来管理其他未知扩展
  74. // 在这种情况下,Android将显示设备上安装的所有应用程序
  75. // 因此您可以选择使用哪个应用程序
  76. intent.setDataAndType(uri, "*/*");
  77. }
  78. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  79. context.startActivity(intent);
  80. } else {
  81. Toast.makeText(context, "文件不存在", Toast.LENGTH_SHORT).show();
  82. }
  83. }

manifest.xml

  1. <provider
  2. android:name="androidx.core.content.FileProvider"
  3. android:authorities="com.zg.pdfdemo.fileprovider"
  4. android:exported="false"
  5. android:grantUriPermissions="true">
  6. <meta-data
  7. android:name="android.support.FILE_PROVIDER_PATHS"
  8. android:resource="@xml/provider_paths" />
  9. </provider>

provider_paths

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <paths>
  3. <external-path name="external_files" path="."/>
  4. </paths>

2.4 pdfRender的简单使用

  1. @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  2. private void pdf4() {
  3. path = getExternalFilesDir("").getAbsolutePath() + "/itext_basic.pdf";
  4. try {
  5. // 1.创建文件
  6. File pdfFile = new File(path);
  7. // 2.获取 ParcelFileDescriptor 对象
  8. ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY);
  9. // 3.创建PdfRenderer对象
  10. PdfRenderer renderer = new PdfRenderer(parcelFileDescriptor);
  11. //渲染page数据到bitmap
  12. //1、获取页码数据Page对象
  13. PdfRenderer.Page page = renderer.openPage(0);
  14. int pageCount = renderer.getPageCount();
  15. Log.i("zxd", "pdf4: 总数=" + pageCount);
  16. //2.创建ARGB_8888 的bitmap
  17. Bitmap bitmap = Bitmap.createBitmap(page.getWidth(), page.getHeight(), Bitmap.Config.ARGB_8888);
  18. //3.渲染
  19. page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
  20. //渲染到iv中
  21. binding.iv.setImageBitmap(bitmap);
  22. //关闭当前page数据
  23. page.close();
  24. } catch (IOException e) {
  25. // TODO Auto-generated catch block
  26. e.printStackTrace();
  27. }
  28. }

总结

优点:本身是Android提供的,比较轻量无需依赖第三方SDK,核心代码都是native实现,执行效率比较高

缺点:只能在Android5.0 或以上版本使用,由于实现方式是native 所以无法自己定制渲染算法,以及方式、使用时还需要自己控制线程安全比较繁琐

参考:

[API Reference Document](https://www.apiref.com/)

Android PdfRenderer 简单使用

Android使用pdfRenderer实现PDF展示功能

itext5

发表评论

表情:
评论列表 (有 0 条评论,230人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Itext生成PDF文件

    最近做一个项目的报表,设计导出问题,要求pdf、excel、word。说实话一个字,烦。写个备忘录吧。。。虽然还是很烦 所需依赖:itext-asian-5.2.0.jar