Android中合多图片和文字合成PDF文件---路很长
16lz
2021-01-26
一, Android中合多图片和文字合成PDF文件
如果遇到什么问题可以留言,欢迎你留言,我希望能帮助到你。一直怀着感恩的心,感谢路途遇到过的贵人。
效果图如下:
这个Demo中实现了图片和文字,当然单纯的文字和图片都可以合成pdf。这里我只是展示了图片和文字的合并。文字是写死的。当然你可以通过editText来进行编辑。
如上图就是我们项目中的需求:这一篇我先写pdf的合成。后面关于智能裁剪方面的我会单独写一篇博客。
第二:需要技术:
1.pdf编辑jar:
iTextpdf.jar这个百度很多,很多csdn都需要钱的。这里需要的直接到我项目里面下载或者去官网下载都免费的。提供了图片和文字合成pdf格式文件,以及文件内容的编辑设置,文字居中标题内容等等。以及图片大小和图片的宽高比例,pdf的页面宽度等。都可以让我们编辑出好看的pdf文件。
**2.pdf文件预览:**谷歌提供了预览pdf文件的库
implementation 'com.github.barteksc:android-pdf-viewer:3.1.0-beta.1'
第三:代码部分:源码:
public class Document implements DocListener, IAccessibleElement { public static boolean compress = true; public static boolean plainRandomAccess = false; public static float wmfFontCorrection = 0.86F; protected ArrayList listeners; protected boolean open; protected boolean close; protected Rectangle pageSize; protected float marginLeft; protected float marginRight; protected float marginTop; protected float marginBottom; protected boolean marginMirroring; protected boolean marginMirroringTopBottom; protected String javaScript_onLoad; protected String javaScript_onUnLoad; protected String htmlStyleClass; protected int pageN; protected int chapternumber; protected PdfName role; protected HashMap accessibleAttributes; protected AccessibleElementId id; public Document() { this(PageSize.A4); } /**通过这些构造方法,我想一个pfd的创建随随便便来了吧。 1.第一个默认的是a4纸的大小。 2.第二个是默认距离边缘left,top,right,bootom大小。 3.第三个是设置了很多参数。自己可以看其意思。 **/ public Document(Rectangle pageSize) { this(pageSize, 36.0F, 36.0F, 36.0F, 36.0F); } public Document(Rectangle pageSize, float marginLeft, float marginRight, float marginTop, float marginBottom) { this.listeners = new ArrayList(); this.marginLeft = 0.0F; this.marginRight = 0.0F; this.marginTop = 0.0F; this.marginBottom = 0.0F; this.marginMirroring = false; this.marginMirroringTopBottom = false; this.javaScript_onLoad = null; this.javaScript_onUnLoad = null; this.htmlStyleClass = null; this.pageN = 0; this.chapternumber = 0; this.role = PdfName.DOCUMENT; this.accessibleAttributes = null; this.id = new AccessibleElementId(); this.pageSize = pageSize; this.marginLeft = marginLeft; this.marginRight = marginRight; this.marginTop = marginTop; this.marginBottom = marginBottom; } public void addDocListener(DocListener listener) { this.listeners.add(listener); if (listener instanceof IAccessibleElement) { IAccessibleElement ae = (IAccessibleElement)listener; ae.setRole(this.role); ae.setId(this.id); if (this.accessibleAttributes != null) { Iterator i$ = this.accessibleAttributes.keySet().iterator(); while(i$.hasNext()) { PdfName key = (PdfName)i$.next(); ae.setAccessibleAttribute(key, (PdfObject)this.accessibleAttributes.get(key)); } } } } public void removeDocListener(DocListener listener) { this.listeners.remove(listener); } /**这里的add方法为我们提供了图文混排的基础 document.add(Element); 这里的Element我们可以看源码: public interface Element { int HEADER = 0;//头部 int TITLE = 1;//标题 int SUBJECT = 2; int KEYWORDS = 3; int AUTHOR = 4; int PRODUCER = 5; int CREATIONDATE = 6; int CREATOR = 7; int LANGUAGE = 8; int CHUNK = 10; int PHRASE = 11; int PARAGRAPH = 12; int SECTION = 13; int LIST = 14; int LISTITEM = 15; int CHAPTER = 16; int ANCHOR = 17; int PTABLE = 23; int ANNOTATION = 29; int RECTANGLE = 30; int JPEG = 32;//图片 int JPEG2000 = 33;//图片 int IMGRAW = 34; int IMGTEMPLATE = 35; int JBIG2 = 36; int DIV = 37; int MARKED = 50; int YMARK = 55; int WRITABLE_DIRECT = 666; int ALIGN_UNDEFINED = -1; int ALIGN_LEFT = 0; int ALIGN_CENTER = 1; int ALIGN_RIGHT = 2; int ALIGN_JUSTIFIED = 3; int ALIGN_TOP = 4; int ALIGN_MIDDLE = 5; int ALIGN_BOTTOM = 6; int ALIGN_BASELINE = 7; int ALIGN_JUSTIFIED_ALL = 8; int CCITTG4 = 256; int CCITTG3_1D = 257; int CCITTG3_2D = 258; int CCITT_BLACKIS1 = 1; int CCITT_ENCODEDBYTEALIGN = 2; int CCITT_ENDOFLINE = 4; int CCITT_ENDOFBLOCK = 8; **/ public boolean add(Element element) throws DocumentException { if (this.close) { throw new DocumentException(MessageLocalization.getComposedMessage("the.document.has.been.closed.you.can.t.add.any.elements", new Object[0])); } else if (!this.open && element.isContent()) { throw new DocumentException(MessageLocalization.getComposedMessage("the.document.is.not.open.yet.you.can.only.add.meta.information", new Object[0])); } else { boolean success = false; if (element instanceof ChapterAutoNumber) { this.chapternumber = ((ChapterAutoNumber)element).setAutomaticNumber(this.chapternumber); } DocListener listener; for(Iterator i$ = this.listeners.iterator(); i$.hasNext(); success |= listener.add(element)) { listener = (DocListener)i$.next(); } if (element instanceof LargeElement) { LargeElement e = (LargeElement)element; if (!e.isComplete()) { e.flushContent(); } } return success; } } public void open() { if (!this.close) { this.open = true; } Iterator i$ = this.listeners.iterator(); while(i$.hasNext()) { DocListener listener = (DocListener)i$.next(); listener.setPageSize(this.pageSize); listener.setMargins(this.marginLeft, this.marginRight, this.marginTop, this.marginBottom); listener.open(); } } public boolean setPageSize(Rectangle pageSize) { this.pageSize = pageSize; Iterator i$ = this.listeners.iterator(); while(i$.hasNext()) { DocListener listener = (DocListener)i$.next(); listener.setPageSize(pageSize); } return true; } public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) { this.marginLeft = marginLeft; this.marginRight = marginRight; this.marginTop = marginTop; this.marginBottom = marginBottom; Iterator i$ = this.listeners.iterator(); while(i$.hasNext()) { DocListener listener = (DocListener)i$.next(); listener.setMargins(marginLeft, marginRight, marginTop, marginBottom); } return true; } public boolean newPage() { if (this.open && !this.close) { Iterator i$ = this.listeners.iterator(); while(i$.hasNext()) { DocListener listener = (DocListener)i$.next(); listener.newPage(); } return true; } else { return false; } } public void resetPageCount() { this.pageN = 0; Iterator i$ = this.listeners.iterator(); while(i$.hasNext()) { DocListener listener = (DocListener)i$.next(); listener.resetPageCount(); } } //设置页面的个数。每一页是一个A4纸张的大小 public void setPageCount(int pageN) { this.pageN = pageN; Iterator i$ = this.listeners.iterator(); while(i$.hasNext()) { DocListener listener = (DocListener)i$.next(); listener.setPageCount(pageN); } } public int getPageNumber() { return this.pageN; } //关闭。 public void close() { if (!this.close) { this.open = false; this.close = true; } Iterator i$ = this.listeners.iterator(); while(i$.hasNext()) { DocListener listener = (DocListener)i$.next(); listener.close(); } } //添加标题头。直接调用或者写个工具类就行。 public boolean addHeader(String name, String content) { try { return this.add(new Header(name, content)); } catch (DocumentException var4) { throw new ExceptionConverter(var4); } } //这是标题主题 public boolean addTitle(String title) { try { return this.add(new Meta(1, title)); } catch (DocumentException var3) { throw new ExceptionConverter(var3); } } //设置副主题 public boolean addSubject(String subject) { try { return this.add(new Meta(2, subject)); } catch (DocumentException var3) { throw new ExceptionConverter(var3); } } public boolean addKeywords(String keywords) { try { return this.add(new Meta(3, keywords)); } catch (DocumentException var3) { throw new ExceptionConverter(var3); } } public boolean addAuthor(String author) { try { return this.add(new Meta(4, author)); } catch (DocumentException var3) { throw new ExceptionConverter(var3); } } public boolean addCreator(String creator) { try { return this.add(new Meta(7, creator)); } catch (DocumentException var3) { throw new ExceptionConverter(var3); } } public boolean addProducer() { try { return this.add(new Meta(5, Version.getInstance().getVersion())); } catch (DocumentException var2) { throw new ExceptionConverter(var2); } } /**这里进行语言的设置。我们可以通过这个来进行字体的设置**/ public boolean addLanguage(String language) { try { return this.add(new Meta(8, language)); } catch (DocumentException var3) { throw new ExceptionConverter(var3); } } public boolean addCreationDate() { try { SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); return this.add(new Meta(6, sdf.format(new Date()))); } catch (DocumentException var2) { throw new ExceptionConverter(var2); } } public float leftMargin() { return this.marginLeft; } public float rightMargin() { return this.marginRight; } public float topMargin() { return this.marginTop; } public float bottomMargin() { return this.marginBottom; } public float left() { return this.pageSize.getLeft(this.marginLeft); } public float right() { return this.pageSize.getRight(this.marginRight); } public float top() { return this.pageSize.getTop(this.marginTop); } public float bottom() { return this.pageSize.getBottom(this.marginBottom); } public float left(float margin) { return this.pageSize.getLeft(this.marginLeft + margin); } public float right(float margin) { return this.pageSize.getRight(this.marginRight + margin); } public float top(float margin) { return this.pageSize.getTop(this.marginTop + margin); } public float bottom(float margin) { return this.pageSize.getBottom(this.marginBottom + margin); } public Rectangle getPageSize() { return this.pageSize; } public boolean isOpen() { return this.open; } public void setJavaScript_onLoad(String code) { this.javaScript_onLoad = code; } public String getJavaScript_onLoad() { return this.javaScript_onLoad; } public void setJavaScript_onUnLoad(String code) { this.javaScript_onUnLoad = code; } public String getJavaScript_onUnLoad() { return this.javaScript_onUnLoad; } public void setHtmlStyleClass(String htmlStyleClass) { this.htmlStyleClass = htmlStyleClass; } public String getHtmlStyleClass() { return this.htmlStyleClass; } public boolean setMarginMirroring(boolean marginMirroring) { this.marginMirroring = marginMirroring; Iterator i$ = this.listeners.iterator(); while(i$.hasNext()) { Object element = (DocListener)i$.next(); DocListener listener = (DocListener)element; listener.setMarginMirroring(marginMirroring); } return true; } public boolean setMarginMirroringTopBottom(boolean marginMirroringTopBottom) { this.marginMirroringTopBottom = marginMirroringTopBottom; Iterator i$ = this.listeners.iterator(); while(i$.hasNext()) { Object element = (DocListener)i$.next(); DocListener listener = (DocListener)element; listener.setMarginMirroringTopBottom(marginMirroringTopBottom); } return true; } public boolean isMarginMirroring() { return this.marginMirroring; } public PdfObject getAccessibleAttribute(PdfName key) { return this.accessibleAttributes != null ? (PdfObject)this.accessibleAttributes.get(key) : null; } public void setAccessibleAttribute(PdfName key, PdfObject value) { if (this.accessibleAttributes == null) { this.accessibleAttributes = new HashMap(); } this.accessibleAttributes.put(key, value); } public HashMap getAccessibleAttributes() { return this.accessibleAttributes; } public PdfName getRole() { return this.role; } public void setRole(PdfName role) { this.role = role; } public AccessibleElementId getId() { return this.id; } public void setId(AccessibleElementId id) { this.id = id; } public boolean isInline() { return false; }}
当然根据上面自己可以丰富自己的工具类通过构造这模式:
package com.example.luhenchang_pdf.pdfutils;import android.support.annotation.NonNull;import com.itextpdf.text.Document;import com.itextpdf.text.DocumentException;import com.itextpdf.text.Element;import com.itextpdf.text.Font;import com.itextpdf.text.Image;import com.itextpdf.text.PageSize;import com.itextpdf.text.Paragraph;import com.itextpdf.text.pdf.BaseFont;import com.itextpdf.text.pdf.PdfWriter;import com.itextpdf.text.pdf.codec.PngImage;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;public class PdfItextUtil {//转换 private Document document; // savePath:保存pdf的路径 public PdfItextUtil(String savePath) throws Exception { //创建新的PDF文档:A4大小,左右上下边框均为0 document = new Document(PageSize.ROYAL_QUARTO,50,50,0,0); //获取PDF书写器 PdfWriter.getInstance(document, new FileOutputStream(savePath)); //打开文档 document.open(); } public void close(){ if (document.isOpen()) { document.close(); } } // 添加图片到pdf中,这张图片在pdf中居中显示 // imgPath:图片的路径,我使用的是sdcard中图片 // imgWidth:图片在pdf中所占的宽 // imgHeight:图片在pdf中所占的高 public PdfItextUtil addImageToPdfCenterH(@NonNull String imgPath, float imgWidth, float imgHeight) throws IOException, DocumentException { //获取图片 Image img = Image.getInstance(imgPath); img.setAlignment(Element.ALIGN_CENTER); img.scaleToFit(imgWidth,imgHeight); //添加到PDF文档 document.add(img); return this; } public PdfItextUtil addPngToPdf(InputStream inputStream) throws DocumentException, IOException { Image img = PngImage.getImage(inputStream); img.setAlignment(Element.ALIGN_CENTER); //添加到PDF文档 document.add(img); return this; } // 添加文本到pdf中 public PdfItextUtil addTextToPdf(String content) throws DocumentException { Paragraph elements = new Paragraph(content, setChineseFont()); elements.setAlignment(Element.ALIGN_BASELINE);// elements.setIndentationLeft(55); //设置距离左边的距离 document.add(elements); // result为保存的字符串 return this; } // 给pdf添加个标题,居中黑体 public PdfItextUtil addTitleToPdf(String title){ try { Paragraph elements = new Paragraph(title, setChineseTiltleFont(18)); elements.setAlignment(Element.ALIGN_CENTER); document.add(elements); // result为保存的字符串 } catch (DocumentException e) { e.printStackTrace(); } return this; } private Font setChineseFont() { return setChineseFont(12); } private Font setChineseFont(int size) { BaseFont bf; Font fontChinese = null; try { // STSong-Light : Adobe的字体 // UniGB-UCS2-H : pdf 字体 bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); fontChinese = new Font(bf, size, Font.NORMAL); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return fontChinese; } private Font setChineseTiltleFont(int size) { BaseFont bf; Font fontChinese = null; try { // STSong-Light : Adobe的字体 // UniGB-UCS2-H : pdf 字体 bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); fontChinese = new Font(bf, size, Font.BOLD); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return fontChinese; }}
项目地址码云:
更多相关文章
- Android中的缓存策略—拉取网络图片,缓存本地
- Android(安卓)Studio精彩案例(一)《ActionBar和 ViewPager版仿网
- Android设置里面默认存储器选项(default write disk)的实现
- android 新闻图片加载,缓存处理
- Android(安卓)使用ColorMatrix改变图片颜色
- Android(安卓)图片获取及上传
- android手机震动的节奏例子--Vibrator对象及周期运用
- 使用Glide替换Picasso经验小结
- Android学习之 那些让我生疏的配置属性