How Do I Customize the Appearance of PSPDFKit When Using React Native?

Q: How Do I Customize the Appearance of PSPDFKit When Using React Native?

A: To customize the appearance of user interface elements when using the PSPDFKit React Native Library for iOS, we recommend doing it directly in Objective-C, as this is simply a lot easier than exposing each and every single element to the javascript side.

As an example, consider we want to change the appearance of the navigation bar and the toolbars. We can add the following helper methods in the RCTPSPDFKitManager.m file:

- (void)customizeAppearanceOfNavigationBar {
  UIColor *backgroundColor = [UIColor colorWithRed:1.00 green:0.72 blue:0.30 alpha:1.0];
  UIColor *foregroundColor = [UIColor colorWithWhite:0.0 alpha:1];

  // More info: https://developer.apple.com/documentation/uikit/uinavigationbar#1654334
  UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
  appearance.titleTextAttributes = @{ NSForegroundColorAttributeName: foregroundColor };
  appearance.largeTitleTextAttributes = @{ NSForegroundColorAttributeName: foregroundColor };
  appearance.backgroundColor = backgroundColor;

  // Used when presenting PSPDFViewController directly inside a UINavigationController,
  // for example when using the `PSPDFKit.present` API in React Native.
  UINavigationBar *appearanceProxy = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[UINavigationController.class]];
  appearanceProxy.standardAppearance = appearance;
  appearanceProxy.compactAppearance = appearance;
  appearanceProxy.scrollEdgeAppearance = appearance;
  appearanceProxy.tintColor = foregroundColor;

  // Used when using the `PSPDFKitView` component in React Native.
  // The `PSPDFKitView` is embedded in its own `PSPDFNavigationController`.
  appearanceProxy = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[PSPDFNavigationController.class]];
  appearanceProxy.standardAppearance = appearance;
  appearanceProxy.compactAppearance = appearance;
  appearanceProxy.scrollEdgeAppearance = appearance;
  appearanceProxy.tintColor = foregroundColor;

  // Repeat the same customization steps for
  // [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[PSPDFNavigationController.class, UIPopoverPresentationController.class]];
  // if you want to customize the look of navigation bars in popovers on iPad as well.
}

- (void)customizeAppearanceOfToolbar {
  // Use dynamic colors for light mode and dark mode.
  UIColor *backgroundColor = [UIColor colorWithRed:0.77 green:0.88 blue:0.65 alpha:1.0];
  UIColor *foregroundColor = [UIColor colorWithWhite:0.0 alpha:1];

  // More info: https://developer.apple.com/documentation/uikit/uitoolbar#1652878
  UIToolbarAppearance *appearance = [[UIToolbarAppearance alloc] init];
  appearance.backgroundColor = backgroundColor;

  PSPDFFlexibleToolbar *appearanceProxy = [PSPDFFlexibleToolbar appearance];
  appearanceProxy.standardAppearance = appearance;
  appearanceProxy.compactAppearance = appearance;
  appearanceProxy.tintColor = foregroundColor;
}

Once we have these methods, we can directly call them at the relevant points in the app lifetime. For instance, one appropriate place to perform all the global theming would be to do it immediately after we set the license key in RCTPSPDFKitManager.m in the React Native Library like this:

RCT_REMAP_METHOD(setLicenseKey, setLicenseKey:(NSString *)licenseKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
  if (licenseKey.length > 0) {
    [PSPDFKitGlobal setLicenseKey:licenseKey];
    [self customizeAppearanceOfNavigationBar];
    [self customizeAppearanceOfToolbar];
    resolve(@(YES));
  } else {
    reject(@"error", @"Invalid License Key.", nil);
  }
}

For more information and examples about how to customize the UI by bridging Objective-C code to React Native, please take a look at the following blog posts: