This is the concept of how I do something similar
I programmatically create a vertical LinearLayout and then measure and lay it out to the correct width for the page and full height.
e.g.
linearLayout.setLayoutParams(
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
linearLayout.measure(
// A4 width
View.MeasureSpec.makeMeasureSpec(A4Short,View.MeasureSpec.EXACTLY),
// Full height
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
linearLayout.layout(0, 0, linearLayout.getMeasuredWidth(),
linearLayout.getMeasuredHeight());
Every thing is now measured and sized but the LinearLayout is too long for the page.
Then create a temp holding array for these measured views and add all the child views from the LinearLayout to the temp ArrayList
ArrayList<View> tempViewsArrayList = new ArrayList<>();
for (int childIndex = 0; childIndex < linearLayout.getChildCount(); childIndex++){
tempViewsArrayList.add(linearLayout.getChildAt(childIndex));
}
Because everything is measured and laid out we can just add back the views to the parent LinearLayout only if adding them does not go over the page height we want.
e.g.
// Create the initial PDF page
int A4Short = 594; // Postscript points
int A4Long = 841; // Postscript points
int pageNumber = 1;
PdfDocument.PageInfo.Builder pageBuilder = new
PdfDocument.PageInfo.Builder(A4Short,A4Long, pageNumber);
PdfDocument.PageInfo pageInfo = pageBuilder.create();
PdfDocument.Page page = document.startPage(pageInfo);
boolean childrenToProcess = true;
int currentChildIndexToProcess = 0;
// Loop over all children
while(childrenToProcess){
// Empty the parent LinearLayout at the start of each page
linearLayout.removeAllViews();
// Keep track of current LinearLayout height
int currentHeight = 0;
// Loop through children
while(currentChildIndexToProcess < tempViewsArrayList.size()) {
// Get the currentChild Height
int thisChildHeight =
tempViewsArrayList.get(currentChildIndexToProcess).getHeight();
// Check if we add the current child would the
// view be too big for the page
if((currentHeight + thisChildHeight > pageCanvas.getHeight()){
// Don't process this child as it would be off the page
// start new page instead
break;
}
// Now add the view back
linearLayout.addView(
tempViewsArrayList.get(currentChildIndexToProcess));
// Add the child height to current height
currentHeight += thisChildHeight;
// Move to next child
currentChildIndexToProcess++;
}
// There are enough children to fill the page
// re-layout linear to reposition the children to be in viewable area
// really only needed for pages greater than 1
linearLayout.setLayoutParams(
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
linearLayout.measure(
// A4 width
View.MeasureSpec.makeMeasureSpec(A4Short,View.MeasureSpec.EXACTLY),
// Full height
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
linearLayout.layout(0, 0, linearLayout.getMeasuredWidth(),
linearLayout.getMeasuredHeight());
// Now draw LinearLayout to the PDF page
Canvas canvas = page.getCanvas();
linearLayout.draw(canvase);
// end page
document.finishPage(page);
// See if we have more children to process
if (currentChildIndexToProcess > tempViewsArrayList.size() -1) {
// Stop processing as there are no more children to process
childrenToProcess = false;
} else {
// We need a new page
pageNumber++;
PdfDocument.PageInfo.Builder pageBuilder = new
PdfDocument.PageInfo.Builder(A4Short, A4Long, pageNumber);
PdfDocument.PageInfo pageInfo = pageBuilder.create();
PdfDocument.Page page = document.startPage(pageInfo);
}
}
Note this is a simplification of the code I use as I have headers and footers for each page, so it is not tested but hopefully you get the concept of measure and layout all children so the children view get the correct size that can be then used to rebuild and re-layout the linearLayout multiple times, once for each page.