I have to create PDF from my webView using PdfDocument on Android.
https://developer.android.com/reference/android/graphics/pdf/PdfDocument.html
The pdf is created well but it is only one page document.
// create a new document
PdfDocument document = new PdfDocument();
// create a page description
PageInfo pageInfo = new PageInfo.Builder(width,
height, 1).create();
// start 1st page
Page page = document.startPage(pageInfo);
// draw something on the page
View content = myWebview;
content.draw(page.getCanvas());
// finish 1st page
document.finishPage(page);
// start 2nd page
Page page = document.startPage(pageInfo);
// draw something on the page
View content = someOtherWebview;
content.draw(page.getCanvas());
// finish 2nd page
document.finishPage(page);
// and so on...
FileOutputStream out;
try {
out = new FileOutputStream(fileNameWithPath, false);
// write the document content
document.writeTo(out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// close the document
document.close();
How can I divide webview content in pages?
I am creating an android app that reads a file like a book, but instead of chopping it up and displaying one page at a time, I hide all but one of the sections and then just display the entire file.
So perhaps you could use a similar technique something like:
1. You can hide all of the webview with css
2. reveal one section
3. write to the PDF
4. hide the previous section
5. reveal the next etc.
In your text.html source file read by your webview, wrap each page in div tags like this:
<div id="page1" style="display:hidden;">
Page 1 text
</div>
<div id="page2" style="display:hidden;">
Page 2 text
</div>
<div id="page3" style="display:hidden;">
Page 3 text
</div>
In your Java:
//First you have to enable Javascript
webView.getSettings().setJavaScriptEnabled(true);
//Then run this javascript which will find the first page and reveal it
webView.loadUrl("javascript:document.getElementById('page"+ 1 +"').style.display ='block';");
//reload Webview
webView.loadUrl("C:\Desktop\text.html");
//write to PDF
//repeat for page 2
hope this helps!
Related
I try to fill pdf form. I open and load pdf file by PDFView but how I can fill pdf form?
I try to do this:
File file = new File("/storage/emulated/0/test/ankieta.pdf");
PDFView pdfView = (PDFView) findViewById(R.id.pdfView);
if (file.exists()) {
pdfView.fromFile(file)
.enableSwipe(true) // allows to block changing pages using swipe
.swipeHorizontal(false)
.enableDoubletap(true)
.password(null)
.scrollHandle(null)
.enableAntialiasing(true) // improve rendering a little bit on low-res screens
.spacing(0)
.autoSpacing(false) // add dynamic spacing to fit each page on its own on the screen
.pageSnap(true) // snap pages to screen boundaries
.pageFling(false) // make a fling change only a single page like ViewPager
.nightMode(false)
.onTap(new OnTapListener() {
#Override
public boolean onTap(MotionEvent e) {
return false;
}
})
.load();
}
First make your pdf to editable pdf.
using this site:-https://www.jotform.com/fillable-pdf-form-creator/
in this site generate a field id and save it any where because using this id you can fill pdf of fix postion of pdf and generated pdf save in res->raw->yourpdf
Now write this code
reader = new PdfReader(current.getResources().openRawResource(R.raw.form));
and using this code you can add in pdf
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(file, false));
AcroFields acroFields = stamper.getAcroFields();
acroFields.setField("name", "Hardik Talaviya");
acroFields.setField("enroll", "150040116022");
acroFields.setField("branch", "IT");
acroFields.setField("sem", "8");
stamper.setFormFlattening(true);
stamper.close();
Here name,enroll,branch and sem is my pdf id which can generated when you create editable pdf.
And last save this pdf in your storage it is fill and open it where you want to open.
I hope this can help you!
Thank You.
Another service that can help you fill in a PDF.
www useanvil.com/developers
They have APIs for filling, generating and signing PDFs. The documentation seems pretty good and there is a prewritten node client.
I'm trying to convert WebView's text content to PDF. Using the code below.
PdfDocument.Page page = document.StartPage(new PdfDocument.PageInfo.Builder(webpage.Width, webpage.Height, 1).Create());
webpage.Draw(page.Canvas);
PDF is properly generated but I can't select text from that PDF. Its like WebView content but converted into an image.
But if I try to print same WebView from the print menu and save it as PDF text selection is working and size of the pdf is smaller.
So how can I create PDF from WebView where text is also selectable.
Eg. of text selection.
What you did is printing the web page as an image to the PDF canvas - that's why the size is larger, and you cannot select text. Because the text is not present there as a text object, but as an image.
The reason for this, is that you draw the webview (and not the webpage) to the PDF canvas. That is just like outputting the view itself as a bitmap to the PDF.
What you might want to do is to use an XHTML to PDF rendering library, like iText or Flying Saucer to properly render the XHTML webpage (and not the webview!) to a PDF.
You can use iText library for this, add this dependency in gradle
compile 'com.itextpdf:itextg:5.5.10'
Now convert the webview's text to pdf like this
try {
File mFolder = new File(getExternalFilesDir(null) + "/sample");
File imgFile = new File(mFolder.getAbsolutePath() + "/Test.pdf");
if (!mFolder.exists()) {
mFolder.mkdir();
}
if (!imgFile.exists()) {
imgFile.createNewFile();
}
String webviewText = "<html><body>Your webview's text content </body></html>";
OutputStream file = new FileOutputStream(imgFile);
Document document = new Document();
PdfWriter.getInstance(document, file);
document.open();
HTMLWorker htmlWorker = new HTMLWorker(document);
htmlWorker.parse(new StringReader(webviewText));
document.close();
file.close();
} catch (Exception e) {
e.printStackTrace();
}
<div isLandscape=false style="page-break-after:always">
<p class="title">
this is the first title in the portrait mode
</p>
<div>
this is the content following the first title in portrait mode
</div>
</div>
<div isLandscape=true style="page-break-after:always">
<p class="title">
this is the first title in the Landscape mode
</p>
<div style="page-break-after:always">
this is the content following the first title in Landscape mode
</div>
<p>
This content which is on the next page should be rendered on a landscape
page and all the content in this parent div should continue to be in the
landscape page.
</p>
</div>
<div isLandscape=false style="page-break-after:always">
<p class="title">
this content should be rendered on the portrait page and continue to be on a
portrait page till the end of the parent div tag.
</p>
</div>
I want the first div content to be on the portrait A4 page and the next to be on the landscape A4 page.This should be not by rotation but by actually setting the pagesize.
One of the ways you can achieve this is by parsing to layout elements instead of straight to a file or pdfDocument, and apply the page size modification using page events.
I made a quick example below that switches orientation every X pages:
public void createPdfFromHtml(String htmlSource, String pdfDest, String resoureLoc) throws IOException, InterruptedException {
File pdf = new File(pdfDest);
pdf.getParentFile().mkdirs();
//convertToElements takes the string containing the HTML as input
byte[] bytes = StreamUtil.inputStreamToArray(new FileInputStream(htmlSource));
String html = new String(bytes);
PdfWriter writer = new PdfWriter(pdfDest);
PdfDocument pdfDoc = new PdfDocument(writer);
Document doc = new Document(pdfDoc,pageSize);
// Create the page size modifying event handler
PageSize pageSize = PageSize.A4;
pageSize = pageSize.rotate();//Start in landscape
int differentPageSizeInterval = 5;
PageSizeModifier pageSizeModifier = new PageSizeModifier(doc, differentPageSizeInterval, pageSize);
//Register it to the pdfDocument and set it to trigger at the start of a page
pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE,pageSizeModifier);
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setBaseUri(resoureLoc);
//Convert the html to elements
try {
//parse and return the top level elements of the <body>
List<IElement> elements = HtmlConverter.convertToElements(html, converterProperties);
for (IElement ele : elements) {
//Add the elements to the layout document
doc.add((BlockElement) ele);
}
doc.close();
} catch (PdfException e) {
System.out.println(e);
e.printStackTrace();
}
}
protected class PageSizeModifier implements IEventHandler {
Document doc;
int interval;
int counter;
PageSize pageSize;
public PageSizeModifier(Document doc, int interval,PageSize pageSize) {
this.doc = doc; //A reference to the layout document must be kept so we can change the margins on the fly
this.interval = interval;
this.counter = 1;
this.pageSize = pageSize;//Start out in landscape
}
#Override
public void handleEvent(Event event) {
if(counter == interval){
//Rotate
pageSize = pageSize.rotate();
//For the rendering framework, change the default page size
doc.getPdfDocument().setDefaultPageSize(pageSize);
//because the page was already created, we need to update the various boxes determining the pagesize
//By default, only the trim and mediabox will be present
((PdfDocumentEvent) event).getPage().setMediaBox(pageSize);
((PdfDocumentEvent) event).getPage().setTrimBox(pageSize);
//Reset the counter
counter = 1;
}else{
counter++;
}
}
Am using "itext-5.5.8", trying to insert (one) page of portrait pdf into a main pdf document, code works perfect but after inserting portrait pages automatically changes to landscape pages, don't know why?
CODE:
try {
PdfReader firstPdf = new PdfReader(mainFileWithPath); //main doc
PdfReader secondPdf =new PdfReader(addFileNameWithPath); // inserting pages
PdfStamper stamp = new PdfStamper(firstPdf, new FileOutputStream(outputPDFFile));
int totalNumOfPagesToInsert = secondPdf.getNumberOfPages();
int i =1;
while (i<=totalNumOfPagesToInsert) {
// Get a page(s) from secondPdf with the given pageNo
PdfImportedPage page = stamp.getImportedPage(secondPdf,i);
// insert new page in to the newly created pdf at specified page number.
stamp.insertPage(INSERT_AT_PAGE_NO + (i-1), secondPdf.getPageSize(i));
// copy the content of the page copied from secondPdf.
stamp.getUnderContent(INSERT_AT_PAGE_NO + (i-1)).addTemplate(page, 0, 0);
i++;
}
//close the new created pdf.
stamp.close();
Please give me directions to fix this! Thanks
As Author #Bruno Lowagie mentioned that "didn't take into account that rotation"
Have fixed the issue like ... Code Below ...
try {
PdfReader firstPdf = new PdfReader(mainFileWithPath);
PdfReader secondPdf =new PdfReader(addFileNameWithPath);
// create new pdf with the content from firstPdf
PdfStamper stamp = new PdfStamper(firstPdf, new FileOutputStream(outputPDFFile));
stamp.setRotateContents(false);
int totalNumOfPagesToInsert = secondPdf.getNumberOfPages();
int i =1;
while (i<=totalNumOfPagesToInsert) {
// Get a single page from secondPdf with the given pageNo
PdfImportedPage page = stamp.getImportedPage(secondPdf,i); //Actual working code
// insert new page in to the newly created pdf at specified page number.
// choose page size bas
stamp.insertPage(INSERT_AT_PAGE_NO + (i-1), secondPdf.getPageSizeWithRotation(i)); //Actual working code
// copy the content of the page copied from secondPdf.
stamp.getUnderContent(INSERT_AT_PAGE_NO + (i-1)).addTemplate(page, 0, 0); //Actual working code
i++;
}
//close the new created pdf.
stamp.close();
I am attempting to create a PDF report from a Java ResultSet. If the report was only one page, I would have no problem here. The issue comes from the fact that the report could be anywhere from one to ten pages long. Right now, I have this to create a single-page document:
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDPage.PAGE_SIZE_LETTER);
document.addPage(page);
PDPageContentStream content = new PDPageContentStream(document,page);
So my question is, how do I create pages dynamically as they are needed. Is there an object-oriented answer staring me in the face and I just cannot see it?
As I expected, the answer was staring me right in the face, I just needed someone to point it out for me.
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDPage.PAGE_SIZE_LETTER);
document.addPage(page);
PDPageContentStream content = new PDPageContentStream(document,page);
//generate data for first page
content.close();
//if number of results exceeds what can fit on the first page
page = new PDPage(PDPage.PAGE_SIZE_LETTER);
document.addPage(page);
content = new PDPageContentStream(document,page);
//generate data for second page
content.close();
Thanks to #mkl for the answer.
To Create Multi Page PDF Document using PDFBox:
(a) Create new page, new content stream, Move to Top Left, start writing. While writing each word check whether space required is not crossing mediabox width. If crosses, move to next line leftmost and start writing. Continue writing till the last line of the page.
(b) Close the contentStream and add the current page to the document when the writing operation reaches the last line of the current page,
(c) Repeat steps (a) and (b) till the last record/row/line is written.
PDDocument document = new PDDocument();
PDFont font = PDType1Font.HELVETICA;
//For Each Page:
PDPage page = new PDPage(PDPage.PAGE_SIZE_A4);
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.setFont(font, 12);
contentStream.beginText();
contentStream.moveTextPositionByAmount(100, 700);
contentStream.drawString("PDF BOX TEXT CONTENT");
contentStream.endText();
contentStream.close();
document.addPage(page);
//After All Content is written:
document.save(pdfFile);
document.close();
Hint: Use Font parameters like size/height and remaining media box height to determine the last line of the page.