2015-11-26 7 views
6

Sto provando a creare un semplice documento PDF utilizzando la classe PdfDocument nativa di Androids (da api 19). Quello che voglio è avere un file di layout XML, ad esempio chiamato pdf_doc.xml, e quindi gonfiarlo durante la creazione del PDF. All'interno dello pdf_doc.xml avrei quindi un mucchio di viste che potrebbero essere recuperate nel codice e quindi disegnate sulle pagine PdfDocuments, separatamente. Il problema è che questo crea un file PDF danneggiato.Android PdfDocument danneggiato quando salvato nella memoria esterna

D'altra parte, se ho appena creare un semplice TextView, a mio main_activity.xml (xml dell'attività sto usando quando si crea il PDF) e l'uso che TextView invece, funziona benissimo.

Perché fa differenza se il TextView deriva da un layout gonfiato o dal layout dell'attività? Sto cercando di farlo nel modo sbagliato?

FYI: non riesce anche quando si crea il TextView a livello di programmazione.

Di seguito è riportato il mio codice sorgente. Queste due funzioni sono chiamate subito dopo. Il primo crea il PDF, l'altro lo salva. Il problema è nella vista, chiamato contenuto, che sto ottenendo dal layout gonfiato. Se invece lo metto TextView nel XML di Activity e poi lo prendo dall'attività, come questo act.findViewById(R.id.pdf_text);, funziona come previsto.

Codice:

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); 
    } 
+0

@ FrankN.Stein Forse non ero abbastanza chiaro, ma non ho intenzione di disegnare l'intero layout in una volta. Sto semplicemente prendendo una TextView dal layout e provando a disegnarla. Non riesco a vedere la differenza nel farlo, rispetto al prendere dal layout l'attività sta usando ... –

+0

No per niente. Come ho detto, se prendo un TextView dall'XML dell'attività, posso disegnarlo nella tela delle pagine PdfDocument, ma non posso farlo con TextView da un layout gonfiato a livello di programmazione? –

risposta

1

due suggerimenti:

  1. Dal momento che il mainLayout avrà altezza pari a zero e la larghezza pari a zero (non si è gonfiato in un genitore), provare a scegliere manualmente la posa fuori , chiamando measure() e layout() su di esso, in questo ordine. Dovrai specificare una dimensione in pixel alla quale vuoi che il layout sia ridimensionato.

  2. Chiama out.getFd().sync() dopo out.flush() e prima out.close(). Dubito che questo stia causando il tuo problema specifico qui, ma è una buona idea ed è improbabile che faccia male.

+0

Grazie per due suggerimenti costruttivi. Lo proverò domani mattina! –

+0

Quali sarebbero i parametri per measure() se volessi che il layout riempisse il maggior spazio possibile? AL MASSIMO? –

+0

@ThomasTeilmann: mi batte. Non l'ho provato Non sono sicuro che ci sia "il maggior spazio possibile", dal momento che non esiste un genitore. Dal momento che IIRC devi fornire dimensioni di carta in pixel, usa lo stesso numero di pixel (o forse un po 'meno) per questo, forse. – CommonsWare

Problemi correlati