Pdf generated from scrollview using PdfDocument only prints contents of first page keeping other pages blank

20 views Asked by At

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?

1

There are 1 answers

2
Andrew On

I think your problem is that scrolling is done by canvas translate (pan the canvas) and when you are calling view.scrollTo you are translating the canvas for the screen but you are then asking the view to draw itself to a new canvas that 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.

for(int index = 0; index < ((ViewGroup) viewGroup).getChildCount(); index++) {
    View nextChild = ((ViewGroup) viewGroup).getChildAt(index);
}

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)