কাস্টম ডকুমেন্ট প্রিন্ট করা

কিছু অ্যাপ্লিকেশনের জন্য, যেমন ড্রয়িং অ্যাপ, পৃষ্ঠা লেআউট অ্যাপ এবং অন্যান্য অ্যাপ যা গ্রাফিক আউটপুটের উপর ফোকাস করে, সুন্দর প্রিন্ট করা পৃষ্ঠা তৈরি করা একটি মূল ফিচার। এই ক্ষেত্রে, কোনও ছবি বা 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)
    }
}

জাভা

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 অবজেক্ট নেয়। আপনি এই প্যারামিটার ব্যবহার করে প্রিন্টিং ফ্রেমওয়ার্ককে ইঙ্গিত দিতে এবং আগের প্রিন্টিং সাইকেলের উপর ভিত্তি করে বিকল্প আগে থেকে সেট করতে পারবেন, যার ফলে ব্যবহারকারীর অভিজ্ঞতা উন্নত হবে। এছাড়াও, আপনি এই প্যারামিটার ব্যবহার করে এমন বিকল্প সেট করতে পারেন যা প্রিন্ট করা কন্টেন্টের জন্য আরও উপযুক্ত, যেমন কোনও ফটো ল্যান্ডস্কেপ ওরিয়েন্টেশনে থাকলে প্রিন্ট করার সময় ওরিয়েন্টেশন ল্যান্ডস্কেপ হিসেবে সেট করা।

প্রিন্ট অ্যাডাপ্টার Android প্রিন্ট ফ্রেমওয়ার্কের সাথে ইন্টার‍্যাক্ট করে এবং প্রিন্টিং প্রসেসের ধাপগুলি ম্যানেজ করে। এই প্রসেসে ব্যবহারকারীকে প্রিন্ট করার জন্য ডকুমেন্ট তৈরি করার আগে প্রিন্টার ও প্রিন্ট করার বিকল্প বেছে নিতে হয়। এইসব বিকল্প চূড়ান্ত আউটপুটকে প্রভাবিত করতে পারে কারণ ব্যবহারকারী আলাদা আউটপুট ক্ষমতা, আলাদা পৃষ্ঠার সাইজ বা আলাদা পৃষ্ঠার ওরিয়েন্টেশন সহ প্রিন্টার বেছে নেন। এইসব বেছে নেওয়া হয়ে গেলে, প্রিন্ট ফ্রেমওয়ার্ক আপনার অ্যাডাপ্টারকে প্রিন্ট ডকুমেন্টের লে-আউট তৈরি করতে বলে, যাতে চূড়ান্ত আউটপুট তৈরি করা যায়। ব্যবহারকারী প্রিন্ট বোতামে ট্যাপ করলে, ফ্রেমওয়ার্ক চূড়ান্ত প্রিন্ট ডকুমেন্ট নিয়ে আউটপুটের জন্য প্রিন্ট পরিষেবা প্রদানকারীর কাছে পাঠায়। প্রিন্ট করার প্রক্রিয়া চলাকালীন, ব্যবহারকারী প্রিন্ট করার অ্যাকশন বাতিল করার বিকল্প বেছে নিতে পারেন, তাই আপনার প্রিন্ট অ্যাডাপ্টারকে অবশ্যই বাতিল করার অনুরোধ শুনতে এবং সেই অনুযায়ী কাজ করতে হবে।

PrintDocumentAdapter অ্যাবস্ট্রাক্ট ক্লাসটি প্রিন্টিং লাইফসাইকেল ম্যানেজ করার জন্য ডিজাইন করা হয়েছে, যার চারটি প্রধান কলব্যাক পদ্ধতি রয়েছে। প্রিন্ট ফ্রেমওয়ার্কের সাথে সঠিকভাবে ইন্টার‍্যাক্ট করার জন্য আপনার প্রিন্ট অ্যাডাপ্টারে এইসব পদ্ধতি প্রয়োগ করতে হবে:

  • onStart() - প্রিন্ট প্রসেসের শুরুতে একবার কল করা হয়। আপনার অ্যাপ্লিকেশনে যদি এককালীন প্রস্তুতিমূলক কোনও টাস্ক থাকে, যেমন প্রিন্ট করার জন্য ডেটার স্ন্যাপশট নেওয়া, তাহলে সেগুলি এখানে এক্সিকিউট করুন। আপনার অ্যাডাপ্টারে এই পদ্ধতি প্রয়োগ করার প্রয়োজন নেই।
  • onLayout() - ব্যবহারকারী যখনই প্রিন্ট সেটিং পরিবর্তন করেন, তখনই কল করা হয়, যা আউটপুটকে প্রভাবিত করে, যেমন একটি ভিন্ন পৃষ্ঠার আকার, বা পৃষ্ঠার ওরিয়েন্টেশন, আপনার অ্যাপ্লিকেশনকে প্রিন্ট করার জন্য পৃষ্ঠার লেআউট গণনা করার সুযোগ দেয়। কমপক্ষে, এই পদ্ধতিটি প্রিন্ট করা ডকুমেন্টে কতগুলি পৃষ্ঠা প্রত্যাশিত তা ফেরত দিতে হবে।
  • onWrite() - প্রিন্ট করা হবে এমন ফাইলে প্রিন্ট করা পৃষ্ঠা রেন্ডার করার জন্য কল করা হয়েছে। প্রতিটি onLayout() কলের পরে এই পদ্ধতিটি এক বা একাধিকবার কল করা হতে পারে।
  • onFinish() - প্রিন্ট প্রসেসের শেষে একবার কল করা হয়। আপনার অ্যাপ্লিকেশনে যদি এককালীন টিয়ার-ডাউন টাস্ক থাকে, তাহলে এখানে তা এক্সিকিউট করুন। আপনার অ্যাডাপ্টারে এই পদ্ধতি প্রয়োগ করার প্রয়োজন নেই।

নিম্নলিখিত বিভাগগুলি বর্ণনা করে যে কীভাবে লেআউট এবং লেখার পদ্ধতিগুলি বাস্তবায়ন করা যায়, যা একটি প্রিন্ট অ্যাডাপ্টারের কার্যকারিতার জন্য গুরুত্বপূর্ণ।

মনে রাখবেন: আপনার অ্যাপ্লিকেশনের মূল থ্রেডে এইসব অ্যাডাপ্টার পদ্ধতি কল করা হয়। আপনার ইমপ্লিমেন্টেশনে এইসব পদ্ধতি কার্যকর করতে উল্লেখযোগ্য পরিমাণ সময় লাগবে বলে মনে করলে, আলাদা থ্রেডে সেগুলি কার্যকর করার জন্য ইমপ্লিমেন্ট করুন। যেমন, আপনি লেআউট বা প্রিন্ট ডকুমেন্ট লেখার কাজ আলাদা 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.")
    }
}

জাভা

@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() পদ্ধতি কার্যকর করার তিনটি ফলাফল হতে পারে: সম্পূর্ণ, বাতিল বা ব্যর্থ হওয়া, যেখানে লেআউটের গণনা সম্পূর্ণ করা যায় না। 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()
}

জাভা

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() পদ্ধতিকে কল করে। পদ্ধতির প্যারামিটারগুলি নির্দিষ্ট করে যে কোন পৃষ্ঠাগুলি লেখা উচিত এবং আউটপুট ফাইল ব্যবহার করা উচিত। এই পদ্ধতি প্রয়োগ করার সময়, আপনাকে কন্টেন্টের প্রতিটি অনুরোধ করা পৃষ্ঠা মাল্টি-পেজ পিডিএফ ডকুমেন্ট ফাইলে রেন্ডার করতে হবে। এই প্রসেস সম্পূর্ণ হয়ে গেলে, আপনি কলব্যাক অবজেক্টের onWriteFinished() মেথড কল করেন।

মনে রাখবেন: Android প্রিন্ট ফ্রেমওয়ার্ক onLayout()-এ করা প্রতিটি কলের জন্য onWrite() পদ্ধতি এক বা একাধিকবার কল করতে পারে। এই কারণে, প্রিন্ট কন্টেন্ট লেআউট পরিবর্তন না হলে, প্রিন্ট ডকুমেন্ট অপ্রয়োজনীয়ভাবে আবার লেখা এড়াতে, onLayoutFinished() পদ্ধতির বুলিয়ান প্যারামিটার false-এ সেট করা গুরুত্বপূর্ণ।

মনে রাখবেন: onLayoutFinished() মেথডের বুলিয়ান প্যারামিটার থেকে বোঝা যায় যে শেষ অনুরোধের পর থেকে লেআউট কন্টেন্ট আসলে পরিবর্তিত হয়েছে কিনা। এই প্যারামিটার সঠিকভাবে সেট করলে, প্রিন্ট ফ্রেমওয়ার্ক onLayout() পদ্ধতিকে অপ্রয়োজনীয়ভাবে কল করা এড়িয়ে যেতে পারে, মূলত আগে লেখা প্রিন্ট ডকুমেন্ট ক্যাশে করে এবং পারফর্ম্যান্স উন্নত করে।

নিম্নলিখিত স্যাম্পেলটি PDF ফাইল তৈরি করার জন্য PrintedPdfDocument ক্লাস ব্যবহার করে এই প্রসেসের প্রাথমিক মেকানিক্স দেখায়:

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)

    ...
}

জাভা

@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);

    ...
}

এই স্যাম্পেল পিডিএফ পৃষ্ঠার কন্টেন্ট রেন্ডার করার দায়িত্ব drawPage() মেথডকে দেয়, যা পরবর্তী বিভাগে আলোচনা করা হয়েছে।

লেআউটের মতো, onWrite() পদ্ধতি কার্যকর করার তিনটি ফলাফল হতে পারে: সম্পূর্ণ, বাতিল বা ব্যর্থতা, যেখানে কন্টেন্ট লেখা যাবে না। PrintDocumentAdapter.WriteResultCallback অবজেক্টের উপযুক্ত পদ্ধতি কল করে আপনাকে অবশ্যই এই ফলাফলগুলির মধ্যে একটি নির্দেশ করতে হবে।

মনে রাখবেন: প্রিন্ট করার জন্য কোনও ডকুমেন্ট রেন্ডার করতে অনেক রিসোর্স লাগতে পারে। আপনার অ্যাপ্লিকেশনের প্রধান ইউজার ইন্টারফেস থ্রেড ব্লক করা এড়াতে, আপনাকে আলাদা থ্রেডে পৃষ্ঠা রেন্ডারিং এবং লেখার অপারেশন সম্পাদন করার কথা বিবেচনা করা উচিত, উদাহরণস্বরূপ একটি AsyncTask-এ। অ্যাসিঙ্ক্রোনাস টাস্কের মতো এক্সিকিউশন থ্রেড নিয়ে কাজ করার ব্যাপারে আরও তথ্য পেতে, প্রসেস ও থ্রেড দেখুন।

ড্রয়িং পিডিএফ পৃষ্ঠার কন্টেন্ট

আপনার অ্যাপ্লিকেশন প্রিন্ট করার সময়, আপনার অ্যাপ্লিকেশনকে অবশ্যই একটি PDF ডকুমেন্ট তৈরি করতে হবে এবং প্রিন্ট করার জন্য Android প্রিন্ট ফ্রেমওয়ার্কে এটি পাস করতে হবে। এই উদ্দেশ্যে আপনি যেকোনও PDF জেনারেশন লাইব্রেরি ব্যবহার করতে পারেন। এই টিউটোরিয়াল থেকে আপনি জানতে পারবেন যে কীভাবে PrintedPdfDocument ক্লাস ব্যবহার করে আপনার কন্টেন্ট থেকে পিডিএফ পৃষ্ঠা তৈরি করতে হয়।

PrintedPdfDocument ক্লাসটি একটি Canvas অবজেক্ট ব্যবহার করে পিডিএফ পৃষ্ঠায় উপাদান আঁকার জন্য, যা একটি অ্যাক্টিভিটি লেআউটে আঁকার মতোই। আপনি 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)
    }
}

জাভা

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 ব্যবহার করে পিডিএফ পৃষ্ঠায় আঁকার সময়, এলিমেন্ট পয়েন্টে নির্দিষ্ট করা হয়, যা এক ইঞ্চির ১/৭২ অংশ। পৃষ্ঠার এলিমেন্টের সাইজ নির্দিষ্ট করার জন্য আপনি পরিমাপের এই ইউনিট ব্যবহার করছেন কিনা তা নিশ্চিত করুন। আঁকা এলিমেন্টের পজিশনের জন্য, পৃষ্ঠার উপরে বাঁদিকের কোণে কোঅর্ডিনেট সিস্টেম 0,0 থেকে শুরু হয়।

পরামর্শ: Canvas অবজেক্ট আপনাকে পিডিএফ ডকুমেন্টের প্রান্তে প্রিন্ট এলিমেন্ট রাখার অনুমতি দিলেও, অনেক প্রিন্টার কাগজের প্রান্তে প্রিন্ট করতে পারে না। এই ক্লাস ব্যবহার করে প্রিন্ট ডকুমেন্ট তৈরি করার সময়, পৃষ্ঠার প্রিন্ট করা যায় না এমন প্রান্তের জন্য আপনি অ্যাকাউন্ট তৈরি করেছেন কিনা তা নিশ্চিত করুন।