描画アプリやページ レイアウト アプリなど、アプリの場合は 美しい印刷ページを作ることが重要な機能です。この場合、 画像や HTML ドキュメントを印刷できますこの種の用途の印刷出力には、 フォント、テキストの流れ、改ページ、 グラフィック要素を配置できます。
アプリケーションに合わせて完全にカスタマイズされた印刷出力を作成するには、より多くの プログラミングにかける時間を削減できます。アプリケーションに必要な 印刷フレームワークとの通信、プリンタ設定の調整、ページ要素の描画、 複数ページの印刷を管理する
このレッスンでは、印刷マネージャーに接続する方法、プリンタ アダプターを作成する方法、 印刷用のコンテンツを作成します。
印刷マネージャーへの接続
アプリケーションが印刷プロセスを直接管理する場合は、メッセージの受信後の最初のステップは、
ユーザーが Android 印刷フレームワークに接続してインスタンスを取得するというものです。
(PrintManager
クラスの)このクラスを使用すると、印刷ジョブを初期化できます。
印刷のライフサイクルを開始します。次のコード例は、印刷マネージャーを取得する方法を示しています。
印刷プロセスを開始します。
Kotlin
private fun doPrint() { activity?.also { context -> // Get a PrintManager instance val printManager = context.getSystemService(Context.PRINT_SERVICE) as PrintManager // Set job name, which will be displayed in the print queue val jobName = "${context.getString(R.string.app_name)} Document" // Start a print job, passing in a PrintDocumentAdapter implementation // to handle the generation of a print document printManager.print(jobName, MyPrintDocumentAdapter(context), null) } }
Java
private void doPrint() { // Get a PrintManager instance PrintManager printManager = (PrintManager) getActivity() .getSystemService(Context.PRINT_SERVICE); // Set job name, which will be displayed in the print queue String jobName = getActivity().getString(R.string.app_name) + " Document"; // Start a print job, passing in a PrintDocumentAdapter implementation // to handle the generation of a print document printManager.print(jobName, new MyPrintDocumentAdapter(getActivity()), null); // }
このコード例は、印刷ジョブに名前を付け、印刷ライフサイクルのステップを処理する PrintDocumentAdapter
クラスのインスタンスを設定する方法を示しています。「
プリント アダプター クラスの実装については、次のセクションで説明します。
注: print()
の最後のパラメータは、
メソッドは PrintAttributes
オブジェクトを受け取ります。このパラメータを使用すると、
印刷フレームワークにヒントを提供し、前の印刷サイクルに基づいて事前設定されたオプションを提供します。
ユーザーエクスペリエンスが向上しますこのパラメータを使用して、Google Chat のメッセージ履歴に
(画面の向きを横向きに設定するなど)、印刷するコンテンツに適したオプションです。
指定した向きの写真を印刷すると、その向きの写真が表示されます。
印刷アダプターの作成
印刷アダプタは、Android 印刷フレームワークとやり取りして、 あります。このプロセスでは、ユーザーは作成する前にプリンタと印刷オプションを選択する必要があります 作成します。これらの選択は、ユーザーの選択に応じた最終出力に影響を与える可能性があります。 出力機能、用紙サイズ、ページの向きなどが異なるプリンタです。 これらの選択を行うと、印刷フレームワークはアダプタに対して、 最終出力に向けて準備します。ユーザーが印刷ボタンをタップすると、フレームワークが は、最終的な印刷ドキュメントを受け取り、出力のために印刷プロバイダに渡します。印刷中 ユーザーが印刷アクションのキャンセルを選択できるため、プリンタ アダプターは キャンセルリクエストに対応します
PrintDocumentAdapter
抽象クラスは、
4 つの主要なコールバック メソッドがあります。これらのメソッドを実装する必要があります。
印刷フレームワークと適切にやり取りするには、次のようにプリンタ アダプタに追加します。
onStart()
- 次のときに 1 回呼び出されます 始まります。アプリケーションで 1 回限りの準備タスクが 出力するデータのスナップショットの取得などを実行する場合は、ここで実行します。実装 使用する必要はありません。onLayout()
- 呼び出されるたびに呼び出されます。 ユーザーが、ページサイズの変更、 これにより、アプリはページのレイアウトを計算できます。 印刷するページを指定します。少なくとも、予想されるページ数を返す必要があります。 をご覧ください。onWrite()
- 印刷してレンダリングするために呼び出されます。 変換してファイルとして保存できますこのメソッドは、各エントリの後に 1 回以上呼び出される場合があります。onLayout()
の呼び出し。onFinish()
- 最後に 1 回呼び出される 。アプリケーションに 1 回限りの破棄タスクを実行する必要がある場合は、 ここで実行してください。アダプターでこのメソッドを実装する必要はありません。
以降のセクションでは、レイアウト メソッドと write メソッドの実装方法について説明します。これらのメソッドは、 プリント アダプターが機能するうえで非常に重要です。
注: これらのアダプター メソッドは、アプリのメインスレッドで呼び出されます。条件
実装でこれらのメソッドを実行すると、処理にかなりの時間がかかることが
独立したスレッド内で実行されるように実装する必要があります。たとえば、Terraform の状態を
レイアウトや印刷ドキュメントの書き込み処理は個別の AsyncTask
オブジェクトで行います。
印刷ドキュメント情報の計算
PrintDocumentAdapter
クラスの実装内で、
アプリケーションは、作成するドキュメントの種類を指定し、合計サイズを計算できる必要があります。
印刷ジョブのページ数(印刷ページサイズに関する情報)。
onLayout()
メソッドの実装は、
アダプタがこれらの計算を行い、出力値に関する期待される出力
PrintDocumentInfo
クラス内の印刷ジョブ(ページ数と
できます。次のコード例は、PrintDocumentAdapter
の onLayout()
メソッドの基本的な実装を示しています。
Kotlin
override fun onLayout( oldAttributes: PrintAttributes?, newAttributes: PrintAttributes, cancellationSignal: CancellationSignal?, callback: LayoutResultCallback, extras: Bundle? ) { // Create a new PdfDocument with the requested page attributes pdfDocument = PrintedPdfDocument(activity, newAttributes) // Respond to cancellation request if (cancellationSignal?.isCanceled == true) { callback.onLayoutCancelled() return } // Compute the expected number of printed pages val pages = computePageCount(newAttributes) if (pages > 0) { // Return print information to print framework PrintDocumentInfo.Builder("print_output.pdf") .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT) .setPageCount(pages) .build() .also { info -> // Content layout reflow is complete callback.onLayoutFinished(info, true) } } else { // Otherwise report an error to the print framework callback.onLayoutFailed("Page count calculation failed.") } }
Java
@Override public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle metadata) { // Create a new PdfDocument with the requested page attributes pdfDocument = new PrintedPdfDocument(getActivity(), newAttributes); // Respond to cancellation request if (cancellationSignal.isCanceled() ) { callback.onLayoutCancelled(); return; } // Compute the expected number of printed pages int pages = computePageCount(newAttributes); if (pages > 0) { // Return print information to print framework PrintDocumentInfo info = new PrintDocumentInfo .Builder("print_output.pdf") .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT) .setPageCount(pages) .build(); // Content layout reflow is complete callback.onLayoutFinished(info, true); } else { // Otherwise report an error to the print framework callback.onLayoutFailed("Page count calculation failed."); } }
onLayout()
メソッドの実行は、
完了、キャンセル、失敗の 3 つになります。
レイアウトを完了できません。適切な関数を呼び出して、これらの結果のいずれかを示す必要があります。
PrintDocumentAdapter.LayoutResultCallback
オブジェクトのメソッドを呼び出します。
注:
onLayoutFinished()
メソッドは、レイアウト コンテンツが実際に変更されたかどうかを示します
前回のリクエスト以降の値を示します。このパラメータを適切に設定すると、印刷フレームワークで
onWrite()
メソッドを不必要に呼び出す
基本的には、以前に書き込まれた印刷ドキュメントをキャッシュに保存して、パフォーマンスを向上させます。
onLayout()
の主な処理は次のとおりです。
指定されたプリンタの属性に基づいて、出力として想定されるページ数を計算する。
この数値を計算する方法は、アプリケーションでページをどのようにレイアウトするかによって大きく異なります。
あります。次のコードサンプルは、ページ数が
: 印刷の向きに応じて異なります。
Kotlin
private fun computePageCount(printAttributes: PrintAttributes): Int { var itemsPerPage = 4 // default item count for portrait mode val pageSize = printAttributes.mediaSize if (!pageSize.isPortrait) { // Six items per page in landscape orientation itemsPerPage = 6 } // Determine number of print items val printItemCount: Int = getPrintItemCount() return Math.ceil((printItemCount / itemsPerPage.toDouble())).toInt() }
Java
private int computePageCount(PrintAttributes printAttributes) { int itemsPerPage = 4; // default item count for portrait mode MediaSize pageSize = printAttributes.getMediaSize(); if (!pageSize.isPortrait()) { // Six items per page in landscape orientation itemsPerPage = 6; } // Determine number of print items int printItemCount = getPrintItemCount(); return (int) Math.ceil(printItemCount / itemsPerPage); }
印刷ドキュメント ファイルへの書き込み
印刷出力をファイルに書き込むとき、Android 印刷フレームワークによって、アプリの PrintDocumentAdapter
クラスの onWrite()
メソッドが呼び出されます。このメソッドのパラメータでは、表示するページを
使用される出力ファイルを指定します。次に、このメソッドの実装で、各 Pod に
複数ページの PDF ドキュメント ファイルに変換します。このプロセスが完了すると
コールバック オブジェクトの onWriteFinished()
メソッドを呼び出します。
注: Android 印刷フレームワークは、セッションごとに onWrite()
メソッドを 1 回以上呼び出す
onLayout()
への呼び出し。このため、
ブール値パラメータを設定することが重要です。
印刷コンテンツのレイアウトが変更されていない場合は、onLayoutFinished()
メソッドを false
に設定します。
これにより、印刷ドキュメントの不要な書き換えを回避できます。
注:
onLayoutFinished()
メソッドは、レイアウト コンテンツが実際に変更されたかどうかを示します
前回のリクエスト以降の値を示します。このパラメータを適切に設定すると、印刷フレームワークで
onLayout()
メソッドを不必要に呼び出す
基本的には、以前に書き込まれた印刷ドキュメントをキャッシュに保存して、パフォーマンスを向上させます。
このプロセスの基本的な仕組みを示す次のサンプルは、PrintedPdfDocument
クラスを使用して PDF ファイルを作成しています。
Kotlin
override fun onWrite( pageRanges: Array<out PageRange>, destination: ParcelFileDescriptor, cancellationSignal: CancellationSignal?, callback: WriteResultCallback ) { // Iterate over each page of the document, // check if it's in the output range. for (i in 0 until totalPages) { // Check to see if this page is in the output range. if (containsPage(pageRanges, i)) { // If so, add it to writtenPagesArray. writtenPagesArray.size() // is used to compute the next output page index. writtenPagesArray.append(writtenPagesArray.size(), i) pdfDocument?.startPage(i)?.also { page -> // check for cancellation if (cancellationSignal?.isCanceled == true) { callback.onWriteCancelled() pdfDocument?.close() pdfDocument = null return } // Draw page content for printing drawPage(page) // Rendering is complete, so page can be finalized. pdfDocument?.finishPage(page) } } } // Write PDF document to file try { pdfDocument?.writeTo(FileOutputStream(destination.fileDescriptor)) } catch (e: IOException) { callback.onWriteFailed(e.toString()) return } finally { pdfDocument?.close() pdfDocument = null } val writtenPages = computeWrittenPages() // Signal the print framework the document is complete callback.onWriteFinished(writtenPages) ... }
Java
@Override public void onWrite(final PageRange[] pageRanges, final ParcelFileDescriptor destination, final CancellationSignal cancellationSignal, final WriteResultCallback callback) { // Iterate over each page of the document, // check if it's in the output range. for (int i = 0; i < totalPages; i++) { // Check to see if this page is in the output range. if (containsPage(pageRanges, i)) { // If so, add it to writtenPagesArray. writtenPagesArray.size() // is used to compute the next output page index. writtenPagesArray.append(writtenPagesArray.size(), i); PdfDocument.Page page = pdfDocument.startPage(i); // check for cancellation if (cancellationSignal.isCanceled()) { callback.onWriteCancelled(); pdfDocument.close(); pdfDocument = null; return; } // Draw page content for printing drawPage(page); // Rendering is complete, so page can be finalized. pdfDocument.finishPage(page); } } // Write PDF document to file try { pdfDocument.writeTo(new FileOutputStream( destination.getFileDescriptor())); } catch (IOException e) { callback.onWriteFailed(e.toString()); return; } finally { pdfDocument.close(); pdfDocument = null; } PageRange[] writtenPages = computeWrittenPages(); // Signal the print framework the document is complete callback.onWriteFinished(writtenPages); ... }
このサンプルでは、PDF ページ コンテンツのレンダリングを drawPage()
に委任します。
メソッドを使用します。これについては次のセクションで説明します。
レイアウトと同様に、onWrite()
の実行
メソッドの結果には、完了、キャンセル、失敗の 3 つがあります。
コンテンツを書き込めません。次の呼び出しによって、これらの結果のいずれかを指定する必要があります。
PrintDocumentAdapter.WriteResultCallback
オブジェクトの適切なメソッドを呼び出します。
注: 印刷ドキュメントのレンダリングは、リソースを大量に消費することがあります。イン
アプリのメイン ユーザー インターフェース スレッドがブロックされないようにするために、
ページのレンダリングと書き込みの処理を別のスレッドで実行すると、
AsyncTask
内。
非同期タスクなどの実行スレッドの操作について詳しくは、
プロセス
とスレッドをご覧ください。
PDF ページ コンテンツの描画
アプリケーションで印刷するときは、アプリケーションで PDF ドキュメントを生成して、
印刷用の Android Print Frameworkこの作業には任意の PDF 生成ライブラリを使用できます。
あります。このレッスンでは、PrintedPdfDocument
クラスの使用方法について説明します。
コンテンツから PDF ページを生成できます
PrintedPdfDocument
クラスは Canvas
を使用する
アクティビティ レイアウト上での描画と同様に、PDF ページに要素を描画するオブジェクトです。描画できる
Canvas
描画メソッドを使用して、印刷ページ上に要素を配置します。次の
サンプルコードは、PDF ドキュメント ページにシンプルな要素を描画する方法を示しています。
メソッド:
Kotlin
private fun drawPage(page: PdfDocument.Page) { page.canvas.apply { // units are in points (1/72 of an inch) val titleBaseLine = 72f val leftMargin = 54f val paint = Paint() paint.color = Color.BLACK paint.textSize = 36f drawText("Test Title", leftMargin, titleBaseLine, paint) paint.textSize = 11f drawText("Test paragraph", leftMargin, titleBaseLine + 25, paint) paint.color = Color.BLUE drawRect(100f, 100f, 172f, 172f, paint) } }
Java
private void drawPage(PdfDocument.Page page) { Canvas canvas = page.getCanvas(); // units are in points (1/72 of an inch) int titleBaseLine = 72; int leftMargin = 54; Paint paint = new Paint(); paint.setColor(Color.BLACK); paint.setTextSize(36); canvas.drawText("Test Title", leftMargin, titleBaseLine, paint); paint.setTextSize(11); canvas.drawText("Test paragraph", leftMargin, titleBaseLine + 25, paint); paint.setColor(Color.BLUE); canvas.drawRect(100, 100, 172, 172, paint); }
Canvas
を使用して PDF ページに描画する場合、要素は
1/72 インチになります。サイズを指定する際は、この測定単位を必ず使用してください。
最適化されます。描画された要素の配置については、座標系は 0,0 から始まります。
をクリックします。
ヒント: Canvas
オブジェクトを使用すると、print ジョブを
といった要素が含まれていると、多くのプリンタでは、
1 枚しかありません。印刷する場合は、ページの印刷できない端も考慮してください。
このクラスを使用して印刷ドキュメントを作成します