PDF display options on Android with PdfFragment
Nutrient provides two kinds of fragments for displaying PDF documents:
-
PdfFragment
is meant for users who want to fully customize and control the PDF display. It shows only the document and does not feature additional views like the thumbnail bar, search, outline, etc. -
PdfUiFragment
works like the ready-to-use PDF viewer activities and provides all the features thePdfActivity
provides. You can use this if using aPdfActivity
is not possible because you have to use a specific activity subclass already. However, if at all possible, we still recommend usingPdfActivity
over usingPdfUiFragment
.
Setting up the manifest
No matter which kind of fragment you end up using, the first step before adding either in your activity is to ensure that your application is prepared for displaying and editing PDFs.
Make sure you have the android:largeHeap="true"
property in your <application>
tag in AndroidManifest.xml
. Rendering PDF files can be memory intensive, and this property will ensure your app has enough heap allocated to avoid hitting out-of-memory errors:
<application android:largeHeap="true">
...
</application>
Configuring the fragment
Just like the PdfActivity
, both PdfFragment
and PdfUiFragment
allow passing in a configuration object that defines various options.
PdfFragment
For the PdfFragment
, create the PdfConfiguration
and pass the desired settings, e.g. scroll orientation, scroll mode, and rendering settings:
val configuration = PdfConfiguration.Builder()
.scrollDirection(PageScrollDirection.HORIZONTAL)
.build()
final PdfConfiguration configuration = new PdfConfiguration.Builder() .scrollDirection(PageScrollDirection.HORIZONTAL) .build();
PdfUiFragment
For the PdfUiFragment
use a PdfActivityConfiguration
instead of PdfConfiguration
. Otherwise, the configuration works the same.
Adding fragment to your activity
PdfFragment
Add PdfFragment
to your activity just like you would any other Android fragment. Create the fragment using PdfFragment.newInstance()
and attach it to your activity. This is usually done within the onCreate()
method of your activity. Since fragments are retained over configuration changes, make sure you don’t recreate the fragment if it already exists:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_custom_fragment) // First, try to restore a previously created fragment. If no fragment exists, create a new one. val fragment = supportFragmentManager.findFragmentById(R.id.fragmentContainer) as PdfFragment ?: createFragment(documentUri, configuration) } private fun createFragment(documentUri: Uri, configuration: PdfConfiguration): PdfFragment { val fragment = PdfFragment.newInstance(documentUri, configuration) supportFragmentManager.beginTransaction() .replace(R.id.fragmentContainer, fragment) .commit() return fragment }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_fragment); // First, try to restore a previously created fragment. PdfFragment fragment = (PdfFragment) getSupportFragmentManager() .findFragmentById(R.id.fragmentContainer); // If no fragment exists, create a new one. if (fragment == null) { fragment = PdfFragment.newInstance(documentUri, configuration); getSupportFragmentManager() .beginTransaction() .replace(R.id.fragmentContainer, fragment) .commit(); } }
PdfUiFragment
PdfUiFragment
works similar to how PdfFragment
does, but you should use PdfUiFragmentBuilder
to obtain an instance of PdfUiFragment
:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_custom_fragment) // First, try to restore a previously created fragment. If no fragment exists, create a new one. val fragment = supportFragmentManager.findFragmentById(R.id.fragmentContainer) as PdfUiFragment ?: createFragment(documentUri, configuration) } private fun createFragment(documentUri: Uri, configuration: PdfActivityConfiguration): PdfFragment { val fragment = PdfUiFragmentBuilder.fromUri(this, documentUri) .configuration(configuration) .build() supportFragmentManager.beginTransaction() .replace(R.id.fragmentContainer, fragment) .commit() return fragment }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_fragment); // First, try to restore a previously created fragment. PdfUiFragment fragment = (PdfUiFragment) getSupportFragmentManager() .findFragmentById(R.id.fragmentContainer); // If no fragment exists, create a new one. if (fragment == null) { fragment = PdfUiFragmentBuilder.fromUri(this, documentUri) .configuration(configuration) .build(); getSupportFragmentManager() .beginTransaction() .replace(R.id.fragmentContainer, fragment) .commit(); } }
Make sure your Activity doesn’t have an action bar (e.g. by using a .NoActionBar
theme), because PdfUiFragment
comes with its own.
ℹ️ Note: Since PdfFragment
and PdfUiFragment
extend androidx.fragment.app.Fragment
, your activity needs to subclass FragmentActivity
, which is part of the AndroidX libraries. Once this is done, you can then access the fragment manager using getSupportFragmentManager()
.
Building an activity around PdfFragment
Nutrient ships with all the views used in PdfActivity
as standalone widgets. If you wish to use these existing Nutrient widgets in your custom activities, follow the building an activity around PdfFragment
guide.