一, 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<DocListener> 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<PdfName, PdfObject> 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<PdfName, PdfObject> 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;
}
}