একটি PDF ভিউয়ার বাস্তবায়ন করুন, একটি PDF ভিউয়ার বাস্তবায়ন করুন

PdfViewerFragment হল একটি বিশেষায়িত Fragment যা আপনি আপনার অ্যান্ড্রয়েড অ্যাপ্লিকেশনের মধ্যে PDF ডকুমেন্ট প্রদর্শন করতে ব্যবহার করতে পারেন। PdfViewerFragment PDF রেন্ডারিংকে সহজ করে তোলে, যার ফলে আপনি আপনার অ্যাপের কার্যকারিতার অন্যান্য দিকগুলিতে মনোনিবেশ করতে পারেন।

ফলাফল

PdfViewerFragment ব্যবহার করে একটি অ্যান্ড্রয়েড অ্যাপ্লিকেশনের মধ্যে রেন্ডার করা একটি PDF ডকুমেন্ট।
একটি অ্যাপে প্রদর্শিত PDF ডকুমেন্ট।

সংস্করণের সামঞ্জস্য

PdfViewerFragment ব্যবহার করার জন্য, আপনার অ্যাপ্লিকেশনটিকে ন্যূনতম Android S (API লেভেল 31) এবং SDK এক্সটেনশন লেভেল 13 টার্গেট করতে হবে। যদি এই সামঞ্জস্যের প্রয়োজনীয়তাগুলি পূরণ না হয়, তাহলে লাইব্রেরি একটি UnsupportedOperationException নিক্ষেপ করবে।

আপনি SdkExtensions মডিউল ব্যবহার করে রানটাইমের সময় SDK এক্সটেনশন সংস্করণটি পরীক্ষা করতে পারেন। এটি আপনাকে শর্তসাপেক্ষে টুকরো এবং PDF ডকুমেন্ট লোড করতে সক্ষম করে যদি ডিভাইসটি প্রয়োজনীয় প্রয়োজনীয়তা পূরণ করে।

if (SdkExtensions.getExtensionVersion(Build.VERSION_CODES.S) >= 13) {
    // Load the fragment and document.
}

নির্ভরতা

আপনার অ্যাপ্লিকেশনে PDF ভিউয়ার অন্তর্ভুক্ত করতে, আপনার অ্যাপের মডিউল build.gradle ফাইলে androidx.pdf নির্ভরতা ঘোষণা করুন। PDF লাইব্রেরিটি Google Maven রিপোজিটরি থেকে অ্যাক্সেসযোগ্য।

dependencies {
    val pdfVersion = "1.0.0-alpha0X"
    implementation("androidx.pdf:pdf:pdf-viewer-fragment:$pdfVersion")
}

PdfViewerFragment বৈশিষ্ট্য

PdfViewerFragment পৃষ্ঠাঙ্কিত বিন্যাসে PDF ডকুমেন্ট উপস্থাপন করে, যা তাদের নেভিগেট করা সহজ করে তোলে। দক্ষ লোডিংয়ের জন্য, খণ্ডটি একটি দুই-পাস রেন্ডারিং কৌশল ব্যবহার করে যা ধীরে ধীরে পৃষ্ঠার মাত্রা লোড করে।

মেমোরি ব্যবহার অপ্টিমাইজ করার জন্য, PdfViewerFragment শুধুমাত্র বর্তমানে দৃশ্যমান পৃষ্ঠাগুলি রেন্ডার করে এবং স্ক্রিনের বাইরে থাকা পৃষ্ঠাগুলির জন্য বিটম্যাপ প্রকাশ করে। অতিরিক্তভাবে, PdfViewerFragment একটি ভাসমান অ্যাকশন বোতাম (FAB) রয়েছে যা ডকুমেন্ট URI ধারণকারী একটি অন্তর্নিহিত android.intent.action.ANNOTATE ইন্টেন্ট ফায়ার করে অ্যানোটেশন সমর্থন করে।

বাস্তবায়ন

আপনার অ্যান্ড্রয়েড অ্যাপ্লিকেশনে একটি PDF ভিউয়ার যোগ করা একটি বহু-পদক্ষেপ প্রক্রিয়া।

কার্যকলাপ বিন্যাস তৈরি করুন

পিডিএফ ভিউয়ার হোস্ট করে এমন কার্যকলাপের জন্য লেআউট XML সংজ্ঞায়িত করে শুরু করুন। লেআউটে PdfViewerFragment ধারণ করার জন্য একটি FrameLayout এবং ব্যবহারকারীর ইন্টারঅ্যাকশনের জন্য বোতাম থাকা উচিত, যেমন ডকুমেন্টের মধ্যে অনুসন্ধান করা।

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/pdf_container_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/fragment_container_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <com.google.android.material.button.MaterialButton
        android:id="@+id/search_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/search_string"
        app:strokeWidth="1dp"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

কার্যকলাপ সেট আপ করুন

PdfViewerFragment হোস্ট করা অ্যাক্টিভিটিকে AppCompatActivity প্রসারিত করতে হবে। অ্যাক্টিভিটির onCreate() পদ্ধতিতে, আপনার তৈরি লেআউটে কন্টেন্ট ভিউ সেট করুন এবং প্রয়োজনীয় UI উপাদানগুলি ইনিশিয়ালাইজ করুন।

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val getContentButton: MaterialButton = findViewById(R.id.launch_button)
        val searchButton: MaterialButton = findViewById(R.id.search_button)
    }
}

PdfViewerFragment আরম্ভ করুন

getSupportFragmentManager() থেকে প্রাপ্ত একটি ফ্র্যাগমেন্ট ম্যানেজার ব্যবহার করে PdfViewerFragment এর একটি ইনস্ট্যান্স তৈরি করুন। নতুন একটি তৈরি করার আগে, বিশেষ করে কনফিগারেশন পরিবর্তনের সময়, ফ্র্যাগমেন্টের একটি ইনস্ট্যান্স ইতিমধ্যেই আছে কিনা তা পরীক্ষা করুন।

নিম্নলিখিত উদাহরণে, initializePdfViewerFragment() ফাংশনটি ফ্র্যাগমেন্ট লেনদেনের সৃষ্টি এবং প্রতিশ্রুতি পরিচালনা করে। ফাংশনটি একটি কন্টেইনারে বিদ্যমান ফ্র্যাগমেন্টকে আপনার PdfViewerFragment এর একটি উদাহরণ দিয়ে প্রতিস্থাপন করে।

class MainActivity : AppCompatActivity() {
    @RequiresExtension(extension = Build.VERSION_CODES.S, version = 13)
    private var pdfViewerFragment: PdfViewerFragment? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...

        if (pdfViewerFragment == null) {
            pdfViewerFragment =
                supportFragmentManager
                    .findFragmentByTag(PDF_VIEWER_FRAGMENT_TAG) as PdfViewerFragment?
        }

    }

    // Used to instantiate and commit the fragment.
    @RequiresExtension(extension = Build.VERSION_CODES.S, version = 13)
    private fun initializePdfViewerFragment() {
        // This condition can be skipped if you want to create a new fragment every time.
        if (pdfViewerFragment == null) {
            val fragmentManager: FragmentManager = supportFragmentManager

          // Fragment initialization.
          pdfViewerFragment = PdfViewerFragmentExtended()
          val transaction: FragmentTransaction = fragmentManager.beginTransaction()

          // Replace an existing fragment in a container with an instance of a new fragment.
          transaction.replace(
              R.id.fragment,4_container_view,
              pdfViewerFragment!!,
              PDF_VIEWER_FRAGMENT_TAG
          )
          transaction.commitAllowingStateLoss()
          fragmentManager.executePendingTransactions()
        }
    }

    companion object {
        private const val MIME_TYPE_PDF = "application/pdf"
        private const val PDF_VIEWER_FRAGMENT_TAG = "pdf_viewer_fragment_tag"
    }
}

PdfViewerFragment কার্যকারিতা প্রসারিত করুন

PdfViewerFragment পাবলিক ফাংশনগুলিকে প্রকাশ করে যা আপনি ওভাররাইড করে এর ক্ষমতা বৃদ্ধি করতে পারেন। PdfViewerFragment থেকে উত্তরাধিকারসূত্রে প্রাপ্ত একটি নতুন ক্লাস তৈরি করুন। আপনার সাবক্লাসে, লগিং মেট্রিক্সের মতো কাস্টম লজিক যোগ করার জন্য onLoadDocumentSuccess() এবং onLoadDocumentError() এর মতো পদ্ধতিগুলিকে ওভাররাইড করুন।

@RequiresExtension(extension = Build.VERSION_CODES.S, version = 13)
class PdfViewerFragmentExtended : PdfViewerFragment() {
          private val someLogger : SomeLogger = // ... used to log metrics

          override fun onLoadDocumentSuccess() {
                someLogger.log(/** log document success */)
          }

          override fun onLoadDocumentError(error: Throwable) {
                someLogger.log(/** log document error */, error)
          }
}

যদিও PdfViewerFragment কোনও অন্তর্নির্মিত অনুসন্ধান মেনু নেই, এটি একটি অনুসন্ধান বার সমর্থন করে। আপনি isTextSearchActive API ব্যবহার করে অনুসন্ধান বারের দৃশ্যমানতা নিয়ন্ত্রণ করতে পারেন। ডকুমেন্ট অনুসন্ধান সক্ষম করতে, আপনি আপনার PdfViewerFragment ইনস্ট্যান্সের isTextSearchActive সম্পত্তি সেট করেন।

WindowInsetsCompat সঠিকভাবে কন্টেন্ট ভিউতে পাঠানো হয়েছে কিনা তা নিশ্চিত করতে WindowCompat.setDecorFitsSystemWindows() ব্যবহার করুন, যা সার্চ ভিউয়ের সঠিক অবস্থান নির্ধারণের জন্য প্রয়োজনীয়।

class MainActivity : AppCompatActivity() {
    @RequiresExtension(extension = Build.VERSION_CODES.S, version = 13)
    override fun onCreate(savedInstanceState: Bundle?) {
        // ...
        searchButton.setOnClickListener {
            pdfViewerFragment?.isTextSearchActive =
                pdfViewerFragment?.isTextSearchActive == false
        }

        // Ensure WindowInsetsCompat are passed to content views without being
        // consumed by the decor view. These insets are used to calculate the
        // position of the search view.
        WindowCompat.setDecorFitsSystemWindows(window, false)
    }
}

ফাইল পিকারের সাথে ইন্টিগ্রেট করুন

ব্যবহারকারীদের তাদের ডিভাইস থেকে PDF ফাইল নির্বাচন করার অনুমতি দিতে, PdfViewerFragment Android ফাইল পিকারের সাথে একীভূত করুন। প্রথমে, আপনার কার্যকলাপের লেআউট XML আপডেট করুন যাতে ফাইল পিকার চালু করার জন্য একটি বোতাম অন্তর্ভুক্ত করা হয়।

<...>
    <FrameLayout
        ...
        app:layout_constraintBottom_toTopOf="@+id/launch_button"/>
    // Adding a button to open file picker.
    <com.google.android.material.button.MaterialButton
        android:id="@+id/launch_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/launch_string"
        app:strokeWidth="1dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/search_button"/>

    <com.google.android.material.button.MaterialButton
        ...
        app:layout_constraintStart_toEndOf="@id/launch_button" />

</androidx.constraintlayout.widget.ConstraintLayout>

এরপর, আপনার কার্যকলাপে, registerForActivityResult(GetContent()) ব্যবহার করে ফাইল পিকার চালু করুন। ব্যবহারকারী যখন একটি ফাইল নির্বাচন করেন, তখন কলব্যাক একটি URI প্রদান করে। এরপর আপনি নির্বাচিত PDF লোড এবং প্রদর্শনের জন্য এই URI দিয়ে আপনার PdfViewerFragment ইনস্ট্যান্সের documentUri সম্পত্তি সেট করুন।

class MainActivity : AppCompatActivity() {
    // ...

    private var filePicker: ActivityResultLauncher<String> =
        registerForActivityResult(GetContent()) { uri: Uri? ->
            uri?.let {
                initializePdfViewerFragment()
                pdfViewerFragment?.documentUri = uri
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...
        getContentButton.setOnClickListener { filePicker.launch(MIME_TYPE_PDF) }
    }

    private fun initializePdfViewerFragment() {
        // ...
    }

    companion object {
        private const val MIME_TYPE_PDF = "application/pdf"
        // ...
    }
}

UI কাস্টমাইজ করুন

লাইব্রেরি যে XML অ্যাট্রিবিউট প্রকাশ করে, সেগুলোকে ওভাররাইড করে আপনি PdfViewerFragment এর ইউজার ইন্টারফেস কাস্টমাইজ করতে পারেন। এটি আপনাকে আপনার অ্যাপের ডিজাইনের সাথে মানানসই করে স্ক্রলবার এবং পেজ ইন্ডিকেটরের মতো উপাদানগুলির চেহারা তৈরি করতে সক্ষম করে।

কাস্টমাইজযোগ্য বৈশিষ্ট্যগুলির মধ্যে রয়েছে:

  • fastScrollVerticalThumbDrawable — স্ক্রলবার থাম্বের জন্য ড্রয়যোগ্য সেট করে।
  • fastScrollPageIndicatorBackgroundDrawable — পৃষ্ঠা নির্দেশকের জন্য ব্যাকগ্রাউন্ড ড্রয়েবল সেট করে।
  • fastScrollPageIndicatorMarginEnd — পৃষ্ঠা নির্দেশকের জন্য সঠিক মার্জিন সেট করে। নিশ্চিত করুন যে মার্জিন মানগুলি ধনাত্মক।
  • fastScrollVerticalThumbMarginEnd — উল্লম্ব স্ক্রলবার থাম্বের জন্য ডান মার্জিন সেট করে। নিশ্চিত করুন যে মার্জিনের মান ধনাত্মক।

এই কাস্টমাইজেশনগুলি প্রয়োগ করতে, আপনার XML রিসোর্সে একটি কাস্টম স্টাইল নির্ধারণ করুন।

<resources>
    <style name="pdfContainerStyle">
        <item name="fastScrollVerticalThumbDrawable">@drawable/custom_thumb_drawable</item>
        <item name="fastScrollPageIndicatorBackgroundDrawable">@drawable/custom_page_indicator_background</item>
        <item name="fastScrollVerticalThumbMarginEnd">8dp</item>
    </style>
</resources>

তারপর, PdfViewerFragment.newInstance(stylingOptions) দিয়ে যখন আপনি ফ্র্যাগমেন্টের একটি ইনস্ট্যান্স তৈরি করবেন তখন PdfStylingOptions ব্যবহার করে PdfViewerFragment কে কাস্টম স্টাইল রিসোর্স প্রদান করুন।

private fun initializePdfViewerFragment() {
    // This condition can be skipped if you want to create a new fragment every time.
    if (pdfViewerFragment == null) {
      val fragmentManager: FragmentManager = supportFragmentManager

      // Create styling options.
      val stylingOptions = PdfStylingOptions(R.style.pdfContainerStyle)

      // Fragment initialization.
      pdfViewerFragment = PdfViewerFragment.newInstance(stylingOptions)

      // Execute fragment transaction.
    }
}

যদি আপনি PdfViewerFragment সাবক্লাস করে থাকেন, তাহলে স্টাইলিং অপশন প্রদান করতে সুরক্ষিত কনস্ট্রাক্টর ব্যবহার করুন। এটি নিশ্চিত করে যে আপনার কাস্টম স্টাইলগুলি আপনার এক্সটেন্ডেড ফ্র্যাগমেন্টে সঠিকভাবে প্রয়োগ করা হয়েছে।

class StyledPdfViewerFragment: PdfViewerFragment {

    constructor() : super()

    private constructor(pdfStylingOptions: PdfStylingOptions) : super(pdfStylingOptions)

    companion object {
        fun newInstance(): StyledPdfViewerFragment {
            val stylingOptions = PdfStylingOptions(R.style.pdfContainerStyle)
            return StyledPdfViewerFragment(stylingOptions)
        }
    }
}

সম্পূর্ণ বাস্তবায়ন

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

class MainActivity : AppCompatActivity() {

    private var pdfViewerFragment: PdfViewerFragment? = null
    private var filePicker: ActivityResultLauncher<String> =
        registerForActivityResult(GetContent()) { uri: Uri? ->
            uri?.let {
                initializePdfViewerFragment()
                pdfViewerFragment?.documentUri = uri
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if (pdfViewerFragment == null) {
            pdfViewerFragment =
                supportFragmentManager
                   .findFragmentByTag(PDF_VIEWER_FRAGMENT_TAG) as PdfViewerFragment?
        }

        val getContentButton: MaterialButton = findViewById(R.id.launch_button)
        val searchButton: MaterialButton = findViewById(R.id.search_button)

        getContentButton.setOnClickListener { filePicker.launch(MIME_TYPE_PDF) }
        searchButton.setOnClickListener {
            pdfViewerFragment?.isTextSearchActive = pdfViewerFragment?.isTextSearchActive == false
        }
    }

    private fun initializePdfViewerFragment() {
        // This condition can be skipped if you want to create a new fragment every time.
        if (pdfViewerFragment == null) {
            val fragmentManager: FragmentManager = supportFragmentManager

          // Create styling options.
          // val stylingOptions = PdfStylingOptions(R.style.pdfContainerStyle)

          // Fragment initialization.
          // For customization:
          // pdfViewerFragment = PdfViewerFragment.newInstance(stylingOptions)
          pdfViewerFragment = PdfViewerFragmentExtended()
          val transaction: FragmentTransaction = fragmentManager.beginTransaction()

          // Replace an existing fragment in a container with an instance of a new fragment.
          transaction.replace(
              R.id.fragment_container_view,
              pdfViewerFragment!!,
              PDF_VIEWER_FRAGMENT_TAG
          )
          transaction.commitAllowingStateLoss()
          fragmentManager.executePendingTransactions()
        }
    }

    companion object {
        private const val MIME_TYPE_PDF = "application/pdf"
        private const val PDF_VIEWER_FRAGMENT_TAG = "pdf_viewer_fragment_tag"
    }
}

কোড সম্পর্কে গুরুত্বপূর্ণ বিষয়সমূহ

  • নিশ্চিত করুন যে আপনার প্রকল্পটি ন্যূনতম API স্তর এবং SDK এক্সটেনশনের প্রয়োজনীয়তা পূরণ করে।
  • PdfViewerFragment হোস্টিং অ্যাক্টিভিটি অবশ্যই AppCompatActivity প্রসারিত করবে।
  • আপনি কাস্টম আচরণ যোগ করতে PdfViewerFragment প্রসারিত করতে পারেন।
  • XML অ্যাট্রিবিউটগুলিকে ওভাররাইড করে PdfViewerFragment এর UI কাস্টমাইজ করুন।