---
title: UI customization
description: Learn how to customize the PingOne Recognize SDK UI to create a more seamless and branded user experience in your app.
component: recognize
page_id: recognize:mobile-sdk:mobile-sdk-ui-customization
canonical_url: https://docs.pingidentity.com/recognize/mobile-sdk/mobile-sdk-ui-customization.html
llms_txt: https://docs.pingidentity.com/recognize/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: April 20, 2026
section_ids:
  sdk-v5: SDK v5
  theme: Theme
  android: Android
  ios: iOS
  react-native: React Native
  colors: Colors
  example: Example
  android-2: Android
  ios-2: iOS
  react-native-2: React Native
  text: Text
  introduction: Introduction
  enrollment: Enrollment
  authentication: Authentication
  authentication-without-camera-preview-beta-from-5-4-1: Authentication without camera preview (BETA from 5.4.1)
  live-filters: Live filters
  dynamic-linking: Dynamic linking
  text-example: Text example
  android-3: Android
  ios-3: iOS
  react-native-3: React native
  optional-screens: Optional screens
  enrollment-biomenrollconfig: Enrollment (BiomEnrollConfig)
  android-4: Android
  ios-4: iOS
  react-native-4: React native
  authentication-biomauthconfig: Authentication (BiomAuthConfig)
  android-5: Android
  ios-5: iOS
  react-native-5: React native
  fonts: Fonts
  android-6: Android
  ios-6: iOS
  flutter: Flutter
  haptic-feedback: Haptic feedback
  android-7: Android
  ios-7: iOS
  sdk-v4: SDK v4
---

# UI customization

The PingOne Recognize SDK can be customized to provide a more familiar UX when integrated into your app.

## SDK v5

### Theme

The SDK theme can be customized to `dark`, `light`, or `system`.

PingOne Recognize uses the system theme by default.

#### Android

```kotlin
Keyless.UI.Color.sdkTheme = SdkTheme.SYSTEM

// default theme is SYSTEM
public enum class SdkTheme {
    DARK,
    LIGHT,
    SYSTEM
}
```

#### iOS

```swift
Keyless.UI.Color.sdkTheme = .system

// default theme is system
public enum SDKTheme {
   case dark
   case light
   case system
}
```

#### React Native

```javascript
import Keyless, { SdkTheme } from '@react-native-keyless/sdk';

const ui = new Keyless.UI();
ui.color.sdkTheme = Keyless.SdkTheme.LIGHT;
await Keyless.updateUI(ui);

export enum SdkTheme {
  SYSTEM = 'SYSTEM',
  LIGHT = 'LIGHT',
  DARK = 'DARK',
}
```

### Colors

You can customize the following colors:

* **primary color**: appears most frequently across screens and components.

* **onPrimary color**: used for content shown on top of primary color.

* **accent color**: used for smaller UI details (for example, camera frame borders).

#### Example

##### Android

```kotlin
Keyless.UI.Color.primary = 0xFF1833B8
Keyless.UI.Color.onPrimary = 0xFFFED900
Keyless.UI.Color.accent = 0xFFFED900
```

##### iOS

```swift
Keyless.UI.Color.primary = .magenta
Keyless.UI.Color.onPrimary = .cyan
Keyless.UI.Color.accent = .yellow
```

##### React Native

```javascript
const ui = new Keyless.UI();
ui.color.accent = '#1833B8';
ui.color.primary = '#FFFFFF';
ui.color.accent = '#FED900';
await Keyless.updateUI(ui);
```

### Text

You can customize text across introduction, enrollment, authentication, error, success, and dynamic linking screens.

#### Introduction

* `title`

* `description`

* `cta`

  ![PingOne Recognize introduction screen.](_images/introductionScreen.PNG)

#### Enrollment

Use concise content (ideally up to three lines).

* **Instruction** (`title`, `subtitle`, `tip1`, `tip2`, `tip3`, `continueCta`)

* **Error** (`title`, `subtitle`, `cta`)

* **Process** (`title`, `subtitle`)

* **Success** (`title`, `subtitle`, `cta`)

  ![PingOne Recognize text enrollment screen layout](_images/enrollmentInstructionScreen.PNG)

  ![PingOne Recognize enrollment error screen layout](_images/enrollmentErrorScreen.PNG)

  ![PingOne Recognize enrollment processing screen layout](_images/enrollmentProcessingScreen.PNG)

  ![PingOne Recognize enrollment success screen layout](_images/enrollmentSuccessScreen.PNG)

#### Authentication

Recommended text keys:

* `loading`

* `centerFace`

* `scan`

* `authenticate`

* `success`

  ![PingOne Recognize authentication loading screen layout](_images/authentication_loading.png)

  ![PingOne Recognize authentication centering screen layout](_images/authenticationCenterFace.png)

  ![PingOne Recognize authentication scan screen layout](_images/authenticationScan.png)

  ![PingOne Recognize authentication progress screen layout](_images/authenticationAuthenticate.png)

  ![PingOne Recognize authentication success screen layout](_images/authenticationSuccess.png)

#### Authentication without camera preview (BETA from 5.4.1)

* `lookHere`

* `authenticate`

* `success`

  ![PingOne Recognize camera preview error.](_images/nocamerapreview_white.gif)

#### Live filters

Live filters are dynamic camera guidance messages and aren't individually configurable. Localization is supported.

![PingOne Recognize live filters preview](_images/Screenshot-2025-10-03-at-11-03-38.png)

![PingOne Recognize live feedback messages](_images/Screenshot-2025-10-03-at-10-58-01.png)

#### Dynamic linking

`Authentication.PayloadConfirmation` keys:

* `title`

* `subtitle`

* `denyCta`

* `approveCta`

  ![PingOne Recognize authentication payload confirmation](_images/authenticationDynamicLinking.png)

#### Text example

##### Android

```kotlin
// Custom text for introduction
Keyless.UI.Text.Introduction.title = "(custom) {p1recognize} Secure Authentication"
Keyless.UI.Text.Introduction.description = "(custom) Hereon, you will start face scanning..."
Keyless.UI.Text.Introduction.cta = "(custom) Continue"

// Custom text for enrollment
Keyless.UI.Text.Enrollment.Instruction.title = "(custom) Enroll your face"
Keyless.UI.Text.Enrollment.Instruction.description = "(custom) On the next screen, we will take a photo of your face to create your account."
Keyless.UI.Text.Enrollment.Instruction.tip1 = "(custom) Center your face in the frame"
Keyless.UI.Text.Enrollment.Instruction.tip2 = "(custom) Look directly at the screen"
Keyless.UI.Text.Enrollment.Instruction.tip3 = "(custom) Ensure you are in a well-lit area"
Keyless.UI.Text.Enrollment.Instruction.continueCta = "(custom) Continue"

// Custom text for authentication
Keyless.UI.Text.Authentication.Step1.text1 = "(custom) Please look into the camera"
Keyless.UI.Text.Authentication.Step2.text1 = "(custom) Communicating with the {p1recognize} network"
Keyless.UI.Text.Authentication.Step3.text1 = "(custom) Approved"

// Custom text for dynamic linking
Keyless.UI.Text.Authentication.PayloadConfirmation.title = "(custom) Authentication request"
Keyless.UI.Text.Authentication.PayloadConfirmation.subtitle = "(custom) Please, approve the payment to complete the process"
Keyless.UI.Text.Authentication.PayloadConfirmation.denyCta = "(custom) Deny"
Keyless.UI.Text.Authentication.PayloadConfirmation.approveCta = "(custom) Approve"
```

##### iOS

```swift
Keyless.UI.Text.Introduction.title = "(custom) {p1recognize} Secure Authentication"
Keyless.UI.Text.Introduction.description = "(custom) Hereon, you will start face scanning..."
Keyless.UI.Text.Introduction.cta = "(custom) Continue"

Keyless.UI.Text.Enrollment.Instruction.title = "(custom) Enroll your face"
Keyless.UI.Text.Enrollment.Instruction.description = "(custom) On the next screen, we will take a photo of your face to create your account."
Keyless.UI.Text.Enrollment.Instruction.tip1 = "(custom) Center your face in the frame"
Keyless.UI.Text.Enrollment.Instruction.tip2 = "(custom) Look directly at the screen"
Keyless.UI.Text.Enrollment.Instruction.tip3 = "(custom) Ensure you are in a well-lit area"
Keyless.UI.Text.Enrollment.Instruction.continueCta = "(custom) Continue"

Keyless.UI.Text.Authentication.Step1.text1 = "(custom) Please look into the camera"
Keyless.UI.Text.Authentication.Step2.text1 = "(custom) Communicating with the {p1recognize} network"
Keyless.UI.Text.Authentication.Step3.text1 = "(custom) Approved"
```

##### React native

```javascript
import Keyless from '@react-native-keyless/sdk';

const ui = new Keyless.UI();
ui.text.introduction.title = '(custom) {p1recognize} Secure Authentication';
ui.text.introduction.description = '(custom) Hereon, you will start face scanning...';
ui.text.introduction.cta = '(custom) Continue';

ui.text.authentication.centerFace = '(custom) Please look into the camera';
ui.text.authentication.scan = '(custom) Communicating with the {p1recognize} network';
ui.text.authentication.success = '(custom) Approved';

await Keyless.updateUI(ui);
```

### Optional screens

You can show/hide specific enrollment and authentication steps by setting the corresponding flags to `false`.

|   |                                                        |
| - | ------------------------------------------------------ |
|   | Default value is `true` for all optional screen flags. |

#### Enrollment (BiomEnrollConfig)

* `showInstructionsScreen`

* `showSuccessFeedback`

* `showFailureFeedback`

##### Android

```kotlin
val biomEnrollConfig = BiomEnrollConfig(
    showInstructionsScreen = false,
    showSuccessFeedback = false,
    showFailureFeedback = false
)

Keyless.enroll(
    configuration = biomEnrollConfig,
    onCompletion = { /* handle completion */ }
)
```

##### iOS

```swift
let biomEnrollConfig = BiomEnrollConfig(
    showInstructionsScreen: false,
    showSuccessFeedback: false,
    showFailureFeedback: false
)

Keyless.enroll(
    configuration: biomEnrollConfig,
    onCompletion: { _ in /* handle completion */ }
)
```

##### React native

```javascript
import Keyless, { BiomEnrollConfig } from '@react-native-keyless/sdk';

const enrollConfig = new BiomEnrollConfig({
  showScreenInstructions: false,
  showSuccessFeedback: false,
  showFailureFeedback: false
});

const result = await Keyless.enroll(enrollConfig);
```

#### Authentication (BiomAuthConfig)

* `showSuccessFeedback`

##### Android

```kotlin
val biomAuthConfig = BiomAuthConfig(
    showSuccessFeedback = false
)

Keyless.authenticate(
    configuration = biomAuthConfig,
    onCompletion = { /* handle completion */ }
)
```

##### iOS

```swift
let biomAuthConfig = BiomAuthConfig(
    showSuccessFeedback: false
)

Keyless.authenticate(
    configuration: biomAuthConfig,
    onCompletion: { _ in /* handle completion */ }
)
```

##### React native

```javascript
import Keyless, { BiomAuthConfig } from '@react-native-keyless/sdk';

const config = new BiomAuthConfig({
  showSuccessFeedback: false,
});

const result = await Keyless.enroll(config);
```

### Fonts

You can customize font:

* Android: `android.graphics.Typeface`

* iOS: font name as `String`

Set custom font as early as possible, ideally before calling `Keyless.configure`.

#### Android

```text
Keyless.UI.Font.customFont: Typeface = Typeface.SERIF
```

#### iOS

```text
Keyless.UI.Font.customFont: String = "Serif"
```

#### Flutter

```dart
final uiCustomization = UICustomization(
    customFont: "Serif"
);
```

### Haptic feedback

Haptic feedback can be enabled or disabled. Default is enabled (`true`).

#### Android

```kotlin
Keyless.UI.hapticFeedbackEnabled = true
```

#### iOS

```swift
Keyless.UI.hapticFeedbackEnabled = false
```

## SDK v4

SDK v4 supports equivalent theme, color, text, optional-screen, and font customization patterns.

For implementation details, use the same sections above and adapt to v4-specific APIs:

* Enrollment text keys under `Keyless.UI.Text.Enrollment.Step0/1/2/3`

* Authentication text keys under `Keyless.UI.Text.Authentication.Step1/2/3`

* Optional screen flags:

  * Enrollment: `showScreenInstructions`, `showScreenSuccessFaceCapture`, `showScreenSuccessFlow`

  * Authentication: `showScreenSuccessFlow`

If you are maintaining v4 integrations, keep API naming aligned with your SDK version.
