Getting started with platform adapters
This guide covers creating a minimal platform adapter and using it with NutrientView.
Prerequisites
Set up a working Nutrient Flutter project before using platform adapters. For more information, refer to the Flutter getting started guide.
Requirements
Flutter:
- Flutter SDK 3.27.0 or later
- Dart SDK 3.6.0 or later
Android:
- Android Studio (latest stable version)
- Android NDK
- Minimum SDK version: 21
- Compile SDK version: 35
- Java 17
iOS:
- Xcode 16 or later
- iOS 16.0 or later
- CocoaPods
Web:
- Chrome, Firefox, Safari, or Edge (latest stable version)
- A Nutrient Web SDK license or trial
Creating a configuration adapter
The simplest adapter overrides the configuration hook to customize how the native SDK initializes. This example doesn’t include a controller interface or event handling.
import 'package:nutrient_flutter_android/src/android_platform_adapter.dart';import 'package:nutrient_flutter_android/src/bindings/nutrient_android_sdk_bindings.dart' as android;
class MyAndroidAdapter extends AndroidAdapter { @override Future<void> configureFragment( NutrientViewHandle handle, android.PdfUiFragmentBuilder builder, android.Context context, ) async { await super.configureFragment(handle, builder, context);
final config = android.PdfActivityConfiguration$Builder(context) .layoutMode(android.PageLayoutMode.SINGLE) .scrollDirection( android.PageScrollDirection.VERTICAL) .fitMode(android.PageFitMode.FIT_TO_WIDTH) .searchEnabled(true) .annotationEditingEnabled(true) .build();
builder.configuration(config); }
@override Future<void> onFragmentAttached( android.PdfUiFragment fragment, android.Context context, ) async {}
@override Future<void> onPdfFragmentReady( android.PdfFragment pdfFragment) async {}
@override Future<void> onFragmentDetached() async {}}import 'package:nutrient_flutter_ios/src/ios_platform_adapter.dart';import 'package:nutrient_flutter_ios/src/bindings/nutrient_ios_bindings.dart' as ios;
class MyIOSAdapter extends IOSAdapter { @override void configureView( NutrientViewHandle handle, ios.PSPDFConfigurationBuilder builder, ) { super.configureView(handle, builder);
builder.pageMode = ios.PSPDFPageMode.PSPDFPageModeSingle; builder.scrollDirection = ios.PSPDFScrollDirection .PSPDFScrollDirectionVertical; builder.pageTransition = ios.PSPDFPageTransition .PSPDFPageTransitionScrollContinuous; }
@override Future<void> onViewControllerReady( ios.PSPDFViewController viewController) async {}
@override Future<void> onViewControllerDetached() async {}}import 'package:nutrient_flutter_web/nutrient_flutter_web.dart';
class MyWebAdapter extends NutrientWebAdapter { @override Future<void> configureLoad( NutrientViewHandle handle, Map<String, dynamic> config, ) async { await super.configureLoad(handle, config);
config['layoutMode'] = 'SINGLE'; config['scrollMode'] = 'CONTINUOUS'; config['spreadFitting'] = 'FIT_TO_VIEWPORT'; config['theme'] = 'AUTO'; config['toolbarPlacement'] = 'TOP'; }
@override Future<void> onInstanceLoaded( NutrientWebInstance instance) async { await super.onInstanceLoaded(instance); }
@override Future<void> dispose() async { await super.dispose(); }}Using the adapter with NutrientView
Pass the adapter to NutrientView via the adapter parameter. Use the conditional import factory pattern to create the correct adapter for the current platform. For more information, refer to platform imports.
import 'package:flutter/material.dart';import 'package:nutrient_flutter/nutrient_flutter.dart';
// Conditional import resolves to the correct platform factory.import 'adapters/adapters.dart';
class AdapterExample extends StatelessWidget { final String documentPath;
const AdapterExample({super.key, required this.documentPath});
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('PDF Viewer')), body: NutrientView( documentPath: documentPath, adapter: createAdapter(), ), ); }}Verifying installation
Run your app to verify the adapter is working:
# Androidflutter run -d android
# iOSflutter run -d ios
# Webflutter run -d chromeThe PDF viewer displays your document with the native SDK configuration applied by your adapter.
Troubleshooting
This section addresses common issues with platform imports and adapter lifecycle callbacks.
Import errors when building for a different platform
If you see errors like Target of URI doesn't exist or Dart library 'dart:io' is not available on this platform, your adapter files are importing bindings for the wrong platform. Each adapter file imports only its own platform’s bindings. For more information, refer to platform imports.
Adapter not receiving lifecycle callbacks
Verify that the adapter is passed to NutrientView via the adapter parameter. If the adapter’s lifecycle methods (onPdfFragmentReady, onViewControllerReady, onInstanceLoaded) aren’t being called, check that the adapter is the correct type for the current platform.
Next steps
- Usage patterns — Controller implementation, event listeners, and UI customization examples
- Platform imports — Handle platform-specific imports