I want to generate a pdf document using Android's PdfDocument class by scrolling through contents of a scrollView.
Right now, correct number of pages are being generated but contents are printed only on first page of pdf. Other generated pages remain blank.
public void toPdf(ScrollView view) {
PdfDocument document = new PdfDocument();
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
int totalHeight = scrollView.getChildAt(0).getHeight();
int pageCount = (int) Math.ceil((double) totalHeight / pageHeight);
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(pageWidth, pageHeight, 1).create();
PdfDocument.Page page = document.startPage(pageInfo);
Canvas canvas = page.getCanvas();
int savedContentOffset = view.getScrollY();
int savedContentInset = view.getPaddingBottom();
view.setClickable(false);
view.setVerticalScrollBarEnabled(false);
view.setHorizontalScrollBarEnabled(false);
view.setPadding(0, 0, 0, 0);
for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) {
view.scrollTo(0, pageIndex * pageHeight);
view.draw(canvas);
document.finishPage(page);
if (pageIndex < pageCount - 1) {
pageInfo = new PdfDocument.PageInfo.Builder(pageWidth, pageHeight, pageIndex + 2).create();
page = document.startPage(pageInfo);
canvas = page.getCanvas();
}
}
view.scrollTo(savedContentOffset, 0);
view.setPadding(0, 0, 0, savedContentInset);
view.setClickable(true);
view.setVerticalScrollBarEnabled(true);
view.setHorizontalScrollBarEnabled(true);
// save PDF to a file
savePdfDocument(document);
}
I verified the position of scrollview is being updated correctly. I also tried adding delays between each scroll to ensure the view's contents are written in pdf but it did not help. I am not able to figure why are contents not being written to pdf on other pages except the first page. What am I missing here?
I think your problem is that scrolling is done by canvas translate (pan the canvas) and when you are calling
view.scrollToyou are translating the canvas for the screen but you are then asking the view to draw itself to a newcanvasthat has not had the pan translation applied to it but the clipBounds on the view have been set.Thus the scroll view contents is actually drawn off the bottom on the second page.
A better way to draw the contents of a scrollview type view is actually re-measure and layout all the children of the scrollview in turn and then add them to a linear layout that is drawn to each page if they will fit.
This is better because you won't get a child view that is split across a pdf page as you are likely to with your current method.
The concept of re-measuring and then laying out to a linearlayout for each page is shown in the example https://github.com/Zardozz/RecyclerviewPdf while this might be for a recyclerview the concept would be the same except instead of iterating through the adaptor creating each view from the viewholder you would iterate through the children view.
e.g.
This also allow you to create PDF pages of standard sizes if you want.
As a side note you might be able to replace
view.scrollTo(0, pageIndex * pageHeight);with
canvas.translate(0, pageIndex * pageHeight);to apply the correct translation to the pdf's canvas as well (not ever tried this as it won't produce the best results)