You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio基于iTextG实现ListView内容多页PDF生成问题

Fixing iTextG PDF Pagination for Long ListView Content on Android

Got it, let's tackle this truncation issue head-on. I’ve worked through similar scenarios where ListView content spills beyond a single PDF page, so here’s a practical, step-by-step solution that handles automatic pagination seamlessly.

Core Idea

Instead of trying to capture the entire ListView as one giant bitmap (which causes truncation), we’ll:

  1. Calculate the exact height of each ListView item (even the invisible ones)
  2. Track how much space we’ve used on the current PDF page
  3. Automatically start a new page when the current item won’t fit in the remaining space
  4. Draw each item (and dividers) to the PDF page by page

Step 1: Calculate Total & Individual Item Heights

First, we need a helper method to measure the height of every ListView item—critical because off-screen items haven’t been laid out yet.

private int calculateListViewItemHeight(ListView listView, int position) {
    ListAdapter adapter = listView.getAdapter();
    if (adapter == null || position >= adapter.getCount()) return 0;

    // Inflate and measure the item view
    View listItem = adapter.getView(position, null, listView);
    listItem.measure(
        View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.EXACTLY),
        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
    );
    return listItem.getMeasuredHeight();
}

// Optional: Calculate total height if you want to pre-determine page count
private int calculateTotalListViewHeight(ListView listView) {
    ListAdapter adapter = listView.getAdapter();
    if (adapter == null) return 0;

    int totalHeight = 0;
    for (int i = 0; i < adapter.getCount(); i++) {
        totalHeight += calculateListViewItemHeight(listView, i);
        totalHeight += listView.getDividerHeight(); // Add divider height
    }
    totalHeight -= listView.getDividerHeight(); // Remove extra divider at end
    return totalHeight;
}

Step 2: Generate Paginated PDF

Here’s the core logic that handles pagination. We’ll iterate through each ListView item, check if it fits on the current page, and create new pages as needed.

public void generatePaginatedPdf(Context context, ListView listView, String outputFilePath) throws IOException, DocumentException {
    // Initialize PDF document with A4 page size
    Document document = new Document(PageSize.A4);
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputFilePath));
    document.open();

    // Define page margins (convert mm to points: 1mm = 2.83465pt)
    final float marginLeft = 20 * 2.83465f;
    final float marginRight = 20 * 2.83465f;
    final float marginTop = 20 * 2.83465f;
    final float marginBottom = 20 * 2.83465f;

    // Calculate usable page dimensions
    float usablePageWidth = PageSize.A4.getWidth() - marginLeft - marginRight;
    float usablePageHeight = PageSize.A4.getHeight() - marginTop - marginBottom;

    ListAdapter adapter = listView.getAdapter();
    if (adapter == null) {
        document.close();
        return;
    }

    float currentPageUsedHeight = marginTop; // Track space used on current page
    PdfContentByte canvas = writer.getDirectContent();

    for (int itemIndex = 0; itemIndex < adapter.getCount(); itemIndex++) {
        // Get and measure the current ListView item
        View listItem = adapter.getView(itemIndex, null, listView);
        listItem.measure(
            View.MeasureSpec.makeMeasureSpec((int) usablePageWidth, View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
        );
        listItem.layout(0, 0, listItem.getMeasuredWidth(), listItem.getMeasuredHeight());

        // Convert View to Bitmap
        listItem.setDrawingCacheEnabled(true);
        Bitmap itemBitmap = Bitmap.createBitmap(listItem.getDrawingCache());
        listItem.setDrawingCacheEnabled(false);

        // Calculate scaled item height (maintain aspect ratio)
        float scaledItemHeight = itemBitmap.getHeight() * (usablePageWidth / itemBitmap.getWidth());

        // Check if item fits on current page
        if (currentPageUsedHeight + scaledItemHeight > PageSize.A4.getHeight() - marginBottom) {
            // No space left—start new page
            document.newPage();
            currentPageUsedHeight = marginTop;
        }

        // Draw the item bitmap to PDF
        Image itemImage = Image.getInstance(itemBitmap, null);
        itemImage.setAbsolutePosition(
            marginLeft,
            PageSize.A4.getHeight() - currentPageUsedHeight - scaledItemHeight
        );
        itemImage.scaleToFit(usablePageWidth, scaledItemHeight);
        document.add(itemImage);

        // Update used height (add item height + divider if not last item)
        currentPageUsedHeight += scaledItemHeight;
        if (itemIndex != adapter.getCount() - 1) {
            // Scale divider height to match PDF page width
            float scaledDividerHeight = listView.getDividerHeight() * (usablePageWidth / listView.getWidth());
            currentPageUsedHeight += scaledDividerHeight;
        }

        // Clean up bitmap to avoid memory leaks
        if (!itemBitmap.isRecycled()) {
            itemBitmap.recycle();
        }
    }

    document.close();
}

Key Notes & Troubleshooting

  • Async Content Handling: If your ListView items contain images loaded asynchronously, make sure all content is fully loaded before generating the PDF (use a callback or wait for loading to complete).
  • Theme Consistency: When inflating ListView items, ensure the Context uses the correct theme so the item styling matches what’s displayed on screen.
  • Memory Management: Recycling bitmaps is crucial—large ListViews can cause OOM if bitmaps aren’t properly cleaned up.
  • Custom Item Heights: This solution works even if your ListView has variable-height items, since we measure each item individually.

内容的提问来源于stack exchange,提问作者Olana Kenea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:59:13