将Android PdfDocument保存到外部存储时受损

5
我正在尝试使用Android的本地PdfDocument类(来自API 19)创建一个简单的PDF文档。我想要的是有一个名为pdf_doc.xml的XML布局文件,然后在创建PDF时进行充气。 在pdf_doc.xml内部,我将有一堆视图可以在代码中获取,然后单独绘制到PdfDocuments页面上。 问题是,这会创建一个损坏的PDF文件。
另一方面,如果我只是在我的main_activity.xml中创建一个简单的TextView(即我创建PDF时使用的活动的XML),并使用该TextView,则可以正常工作。
为什么从充气布局或活动布局获得TextView会有差别呢? 我的做法是否错误?
FYI:当以编程方式创建TextView时,它也会失败。
以下是我的源代码。这两个函数在彼此之后立即调用。问题出现在名为content的视图中,我从充气布局中获取它。 如果我将该TextView放入Activity的XML中,然后从activity获取它,如下所示 act.findViewById(R.id.pdf_text); 它就像预期的那样工作。
代码:
    public static PdfDocument createPdf(Activity act){
        PrintAttributes printAttrs = new PrintAttributes.Builder().
                setColorMode(PrintAttributes.COLOR_MODE_COLOR).
                setMediaSize(PrintAttributes.MediaSize.ISO_A4).
                setMinMargins(PrintAttributes.Margins.NO_MARGINS).
                build();

        ViewGroup mainLayout = (ViewGroup) View.inflate(act, R.layout.pdf_doc, null);

        int pageHeight = printAttrs.getMediaSize().getHeightMils() / 1000 * 72;
        int pageWidth = printAttrs.getMediaSize().getWidthMils() / 1000 * 72;

        PdfDocument document = new PrintedPdfDocument(act, printAttrs);
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(pageWidth, pageHeight, 1).create();
        PdfDocument.Page page = document.startPage(pageInfo);

        View content = mainLayout.findViewById(R.id.pdf_text);
        content.draw(page.getCanvas());
        document.finishPage(page);

        return document;
    }

    public static void saveFile(PdfDocument doc){
        String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();
        File myDir = new File(root + "/pdf_test");
        myDir.mkdirs();

        File file = new File(myDir, "test.pdf");

        if (file.exists()) {
            file.delete();
        }

        try {
            FileOutputStream out = new FileOutputStream(file);
            doc.writeTo(out);
            doc.close();
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        String path = file.getAbsolutePath();
        Log.d("pdftest", "path: " + path);
    }

@FrankN.Stein 也许我没有表述清楚,但我并不想一次性绘制整个布局。我只是要从布局中取出一个 TextView 并试图绘制它。我看不出这样做与从活动正在使用的布局中取出 TextView 的区别... - Teilmann
完全不行。就像我说的,如果我从 Activity 的 XML 中获取 TextView,我可以将其绘制到 PdfDocument 页面的画布上,但是我不能用程序动态生成的布局中的 TextView 进行同样的操作吗? - Teilmann
1个回答

1

两个建议:

  1. 由于您的mainLayout没有被充气到父级,因此其高度和宽度都为零,请尝试手动布局,按顺序调用measure()layout()。您需要指定一个以像素为单位的大小,使布局可以被调整大小。

  2. out.flush()之后,在out.close()之前调用out.getFd().sync()。我怀疑这不会导致您在这里的具体问题,但这是一个好主意,不太可能有害。


谢谢你提供的两个建设性的建议。我明天早上会试一下! - Teilmann
如果我想让布局尽可能填充更多的空间,那么measure()的参数应该是什么?AT_MOST? - Teilmann
@ThomasTeilmann:我不知道。我没有尝试过那个。我不确定是否有“尽可能多的空间”,因为没有父级。如果我没记错,你必须以像素为单位提供纸张大小,因此对于此,请使用相同数量的像素(或者可能略少一些)。 - CommonsWare

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接