Android中合多图片和文字合成PDF文件---路很长

一, Android中合多图片和文字合成PDF文件

如果遇到什么问题可以留言,欢迎你留言,我希望能帮助到你。一直怀着感恩的心,感谢路途遇到过的贵人。


效果图如下:
这个Demo中实现了图片和文字,当然单纯的文字和图片都可以合成pdf。这里我只是展示了图片和文字的合并。文字是写死的。当然你可以通过editText来进行编辑。

image

image

如上图就是我们项目中的需求:这一篇我先写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;
    }
}


项目地址码云:

发布了47 篇原创文章 · 获赞 54 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/m0_37667770/article/details/83109311