> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.idenfy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Android SDK UI Customization

> Customize iDenfy Android SDK colors, fonts, and UI elements programmatically or via XML layout files for a fully branded experience.

The Android SDK provides various customization options with *programming code* or *XML files*.

## Getting Started

### Create IdenfyUISettingsV2

Create an instance of the IdenfyUISettingsV2 class:

```kotlin theme={"system"}
    val idenfyUISettingsV2 = IdenfyUISettingsV2.IdenfyUIBuilderV2()
    .build()
```

### Update IdenfySettingsV2

```kotlin theme={"system"}
    val idenfySettingsV2 = IdenfySettingsV2.IdenfyBuilderV2()
    .withIdenfyUISettingsV2(idenfyUISettingsV2)
    ...
    build()
```

The SDK currently supports several ways of customization.

### Which Approach Should You Use?

| Approach             | Complexity | Best for                                           |
| -------------------- | ---------- | -------------------------------------------------- |
| Colors.xml overrides | Low        | Brand color changes only                           |
| Override XML layouts | Medium     | Rearranging or hiding UI elements                  |
| Jetpack Compose      | High       | Full control over layout, fonts, and animations    |
| Custom results view  | Medium     | Replacing the verification-results screen entirely |

## Customization Options

### Customization with IdenfyUISettingsV2

#### Camera OnBoarding View

```kotlin theme={"system"}
    IdenfyUISettingsV2.IdenfyUIBuilderV2()
    /**
     * OnBoarding View acts as additional screen, which helps the user to familiarize themselves with the current step
     * @param idenfyOnBoardingViewTypeEnum Defines onBoarding view type
     */
    .withConfirmationView(idenfyOnBoardingViewTypeEnum: IdenfyOnBoardingViewTypeEnum)
    ...
    build()
```

The possible options of the Camera OnBoarding View:

| IdenfyOnBoardingViewTypeEnum | Description                                                                                                                                            |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `none`                       | OnBoarding view is skipped                                                                                                                             |
| `multipleStatic`             | Shows an onBoarding view before EVERY step of the verification process with a static instruction list (This is a default setting starting 7.x version) |

<video width={250} autoPlay loop muted playsInline>
  <source src="https://mintcdn.com/idenfy/5qhBgHm1UiZRPBZg/images/tutorials/mobile/gifs/camera_onboarding_multiple_static.mp4?fit=max&auto=format&n=5qhBgHm1UiZRPBZg&q=85&s=b40084e17a7027781bccc84fbe7b3e2e" type="video/mp4" data-path="images/tutorials/mobile/gifs/camera_onboarding_multiple_static.mp4" />
</video>

#### Joined Country and Document Selection

Since SDK version 9.0.0, this setting is enabled by default and the country and document selection views are joined into one.

<img alt="New Country & Document selection" width="250" src="https://mintcdn.com/idenfy/5qhBgHm1UiZRPBZg/images/mobile/migrations/9.0.0/new_country_document_selection.png?fit=max&auto=format&n=5qhBgHm1UiZRPBZg&q=85&s=d254d0394277fc775bad0b8fe5857c6d" data-path="images/mobile/migrations/9.0.0/new_country_document_selection.png" />

```kotlin theme={"system"}
    IdenfyUISettingsV2.IdenfyUIBuilderV2()
    /**
     * An option to choose whether country and document selection views are joined or separate
     * @param withCountryAndDocumentSelectionJoined: sets the visibility of joined country and document selection view
     */
    .withCountryAndDocumentSelectionJoined(withCountryAndDocumentSelectionJoined: Boolean)
    ...
    build()
```

#### Language Selection

```kotlin theme={"system"}
    IdenfyUISettingsV2.IdenfyUIBuilderV2()
    /**
     * Enables language selection window, which provides an option to change the locale
     * @param isLanguageSelectionNeeded Changes visibility of locale selection icon.
    */
    .withLanguageSelection(isLanguageSelectionNeeded: Boolean)
    ...
    build()
```

#### Mismatch Tags Alert Visibility

```kotlin theme={"system"}
    IdenfyUISettingsV2.IdenfyUIBuilderV2()
    /**
     * An option to choose whether mismatch tags alert is visible
     * @param mismatchTagsAlert: set the visibility of mismatch tags alert
    */
    .withMismatchTagsAlert(mismatchTagsAlert: Boolean)
    ...
    build()
```

#### Document Camera Rectangle Visibility

Since some documents are non-regular size, you can hide the camera rectangle. This way the whole screen is dedicated to document capturing.

The rectangle can be hidden for **all** document types:

```kotlin theme={"system"}
    /**
    * Camera rectangle will be hidden for ALL countries and document types
    */
    val idenfyUISettingsV2 =
        IdenfyUISettingsV2.IdenfyUIBuilderV2()
          .withDocumentFrameVisibility(DocumentCameraFrameVisibility.HiddenForAllCountriesAndDocumentTypes)
          .build()
```

Or for **specific countries and document types**:

```kotlin theme={"system"}
    /**
    * Camera rectangle will be hidden ONLY for Lithuanian passport
    */
    val countryDocumentMap: MutableMap<String, List<DocumentTypeEnum>> = mutableMapOf()
    countryDocumentMap["LT"] = mutableListOf(DocumentTypeEnum.PASSPORT)
    val documentCameraFrameVisibility = DocumentCameraFrameVisibility.HiddenForSpecificCountriesAndDocumentTypes(countryDocumentMap)

    val idenfyUISettingsV2 = IdenfyUISettingsV2.IdenfyUIBuilderV2()
        .withDocumentFrameVisibility(documentCameraFrameVisibility)
        .build()
```

#### Adding Instructions in Camera Session

The SDK provides informative instructions during the verification session. They can provide valuable information for the user and help tackle common issues: bad lighting, wrong document side, etc. Instructions can be customized by changing all UI elements or even using your MP4 video files. Instructions are configured by your backend settings and can be overridden with the SDK settings.

**Using IdenfyInstructionsEnum dialog:**

**Using IdenfyInstructionsEnum none:**

Enable instructions in IdenfyUISettingsV2:

```kotlin theme={"system"}
    val idenfyUISettingsV2 = IdenfyUISettingsV2.IdenfyUIBuilderV2()
        .withInstructions(IdenfyInstructionsType.DIALOG)
        ...
        build()
```

### Applying SDK-Wide Color Changes

If **color and asset changes** are the only requirement, they can be easily customized by changing the main colors.

| Color name                | Description                                                                       | Default color value |
| ------------------------- | --------------------------------------------------------------------------------- | ------------------- |
| `idenfyMainColorV2`       | Defines the color of most single-colored assets and focused parts in the SDK.     | #536DFE             |
| `idenfyMainDarkerColorV2` | Defines the color of some focused parts in the SDK, similar to idenfyMainColorV2. | #5D7CE4             |
| `idenfyBackgroundColorV2` | Defines the background color.                                                     | #FBFBFB             |
| `idenfySecondColorV2`     | Defines the text color.                                                           | #F2353B4E           |

**1. Override color names in your app module.**

Create either a new `idenfy_colors.xml` or add the defined colors to your project.

**2. Make color changes:**

```xml theme={"system"}
<resources>
    <color name="idenfyMainColorV2">#7CFC00</color>
    <color name="idenfyMainDarkerColorV2">#7CFC00</color>
</resources>
```

Colors are also applied to images that use a single color from *idenfy drawable resources*. If you override the provided images with icons using more than one color, you can disable the tint on images by overriding the layout styles with the removed tint attribute.

**Before:**

```xml theme={"system"}
<style name="idenfyAppBarLayoutBackButtonStyle">
    <item name="android:tint">
        @color/idenfyMainColorV2
    </item>
</style>
```

**After:**

```xml theme={"system"}
<style name="idenfyAppBarLayoutBackButtonStyle" />
```

### Customization with `styles.xml` or `colors.xml`

Every screen in the SDK uses different `styles.xml` which covers all UI elements visible on that screen. By overriding styles or colors in your app target, you can change the look of the SDK to match your brand guidelines.

You can access the styles.xml and colors.xml [here](https://github.com/idenfy/iDenfyResources/tree/main/sdk/android/).

### Customization with Overriding Layouts of SDK

All layouts in the SDK are structured so that it is easy to override all components to match your brand identity. Requirements for overriding layouts:

* **Do not remove IDs of components** -- this will maintain project stability and avoid runtime crashes.
* **Keep the same layout names** -- if layout names are changed, the SDK layouts will not be overridden.

Find all layouts [here](https://github.com/idenfy/iDenfyResources/tree/main/sdk/android/layouts/).

### Customization by Providing Your Own Implementations of Jetpack Compose Composables

For more advanced customization (fonts, layout structure, etc.), you can provide your own composable implementations.

<Warning>
  This is a new feature that is still in progress. Jetpack Compose is NOT supported in all the views. We strongly suggest trying it out and sharing your feedback with us. More views will be supported in the future.
</Warning>

**1. Create an instance of IdenfyComposableViews**

Use `IdenfyComposeViewBuilder` to create an instance of `IdenfyComposableViews` with your custom composables, which conform to an interface provided by the SDK:

```kotlin theme={"system"}
  val idenfyComposeViews = IdenfyComposeViewBuilder()
    .withManualReviewingIdentificationResultsStatusWaitingComposable { data -> ManualReviewingIdentificationResultsWaitingTestComposable.composeManualView(data) }
    ...
    .build()
```

**2. Pass IdenfyComposableViews instance to the SDK**

```kotlin theme={"system"}
IdenfyController.getInstance().idenfyComposableViews = idenfyComposeViews
```

<Warning>
  Make sure you create an instance of IdenfyComposableViews in the Application class, otherwise your provided composables will be lost after process death.
</Warning>

**3. Pass resources to composables**

`IdenfyComposeViewBuilder` provides a data class with all required resources (images, videos, button actions, etc.) to fulfil the view. Pass this class to your composable:

```kotlin theme={"system"}
val idenfyComposeViews = IdenfyComposeViewBuilder()
    .withManualReviewingIdentificationResultsStatusWaitingComposable { data -> ManualReviewingIdentificationResultsWaitingTestComposable.composeManualView(data) }
    ...
    .build()

@Composable
fun composeManualView(data: IdenfyManualReviewingIdentificationResultsStatusWaitingComposeViewData) {
  ...
}
```

**4. Create the composable**

The data class also contains `IdenfyComposeBases`, which you can use to provide ONLY your customized separate composables. These composables will be composed by the SDK, preserving the intended layout guidelines while displaying your own customized composables.

A minimal example showing how to use `IdenfyComposeBases` to provide custom composables:

```kotlin theme={"system"}
@Composable
fun composeManualView(data: IdenfyManualReviewingIdentificationResultsStatusWaitingComposeViewData) {
    val resources = data.resources
    val composeBases = data.idenfyComposeBases
    val state = resources.state.collectAsState()

    composeBases.manualReviewingIdentificationResultsStatusWaitingComposableBase(
        resources,
        manualReviewingWaitingStatusViewTitle = { title ->
            Text(text = title, textAlign = TextAlign.Center, fontFamily = IdenfyFonts.hkGrotesk)
        },
        manualReviewingWaitingStatusViewDescription = { description ->
            Text(text = description, textAlign = TextAlign.Center, fontFamily = IdenfyFonts.hkGrotesk)
        },
        // Override remaining slots as needed — see the sample app for a complete implementation
    )
}
```

<Note>
  The snippet above is intentionally minimal. Download the [sample app](https://github.com/idenfy/iDenfyResources/blob/main/sdk/android/tutorials/sample/idenfy_sample_android.zip) for a full working example that covers all composable slots, state handling, and button actions.
</Note>

If you want to compose the view entirely by yourself, you are not required to use the `IdenfyComposeBases` class.

<Warning>
  If you are composing the view yourself, make sure you carefully test the views, since the layout will NOT be used as intended and unexpected behavior might occur.
</Warning>

#### Example of the Customization Flow

Download the [sample app](https://github.com/idenfy/iDenfyResources/blob/main/sdk/android/tutorials/sample/idenfy_sample_android.zip). Check the `IdenfyApplication` class, where you will find `IdenfyComposeViewBuilder` with all the composables composed by `IdenfyComposeBases`.

<Warning>
  We strongly suggest taking a look at the example class, since it shows how to collect the view state, pass the resources, and handle button actions.
</Warning>

### Customization by Providing a Custom Verification Results View

To fully customize your verification results waiting view, you can pass your own fragment.

<Warning>
  After supplying your own implementation of the results Fragment, the SDK will not load its own Fragment and will navigate **directly to your own Fragment**.
</Warning>

You can then control when and after which additional steps you want to retry the verification session:

<img alt="Custom Fragment" width="300" src="https://mintlify.s3.us-west-1.amazonaws.com/idenfy/images/tutorials/mobile/gifs/android/custom_waiting_vc_android.gif" />

**1. Create a class that implements IdenfyInProcessIdentificationResultsHandler**

Pass an instance of your created class to the `setIdenfyCallBackHandlerAfterSDKCloses()` method of `IdenfyCallbackController`:

```kotlin theme={"system"}
  val idenfyCallBackHandlerAfterSDKCloses = IdenfyCallbackHandler()
        com.idenfy.idenfySdk.CoreSdkInitialization.IdenfyCallbackController.setIdenfyCallBackHandlerAfterSDKCloses(
            idenfyCallBackHandlerAfterSDKCloses
        )
```

**2. Create an instance of your CustomWaitingViewController**

Return the created instance in the `onIdenfyFlowFinished()` method of your `IdenfyInProcessIdentificationResultsDelegate` implementation:

```kotlin theme={"system"}
    /**
     - Parameter idenfyIdentificationResultStatus: returns a current verification status. This status is updated until FINISHED is returned.
     */
     override fun onIdenfyFlowFinished(idenfyFlowSettings: IdenfyFlowSettings): CustomWaitingFragment {
        return CustomWaitingFragment.FragmentProvided(PartnersCustomWaitingFragment())
    }
```

For details regarding the verification process, see `IdenfyFlowSettings`:

```kotlin theme={"system"}
/**
 Has set of properties for providing information about user verification flow.
 Steps provides an array of steps used during the verification process.
 */
data class IdenfyFlowSettings(val steps: List<Step>)
```

**3. Call a static method of IdenfyCallbackController to continue the flow**

Your `IdenfyInProcessIdentificationResultsHandler` implementation has an `onIdentificationStatusReceived()` method that returns an `IdenfyIdentificationResultStatus`. When `IdenfyIdentificationStatus` is **FINISHED**, call the static `continueFlow()` method of `IdenfyCallbackController`:

```kotlin theme={"system"}
    /**
     - Parameter idenfyIdentificationResultStatus: returns a current verification status. This status is updated until FINISHED is returned.
     */
   override fun onIdentificationStatusReceived(idenfyIdentificationResultStatus: IdenfyIdentificationResultStatus) {
        when (val state = idenfyIdentificationResultStatus.idenfyProcessingResultState) {
            is IdenfyProcessingResultState.FINISHED -> {
                IdenfyCallbackController.continueFlow()
            }
            IdenfyProcessingResultState.PROCESSING -> {
            }
        }
    }
```

`IdenfyIdentificationResultStatus` contains all information about the current state of verification results, which you can use to fully customize your views:

```kotlin theme={"system"}
data class IdenfyIdentificationResultStatus(val idenfyIdentificationStatus: IdenfyIdentificationStatus, val idenfyProcessingResultState: IdenfyProcessingResultState)

sealed class IdenfyProcessingResultState {
    data class FINISHED(val canRetry: Boolean, val retakeSteps: RetakeSteps?): IdenfyProcessingResultState()
    object PROCESSING: IdenfyProcessingResultState()
}

enum class IdenfyIdentificationStatus(val status: String) {
    SUSPECTED("SUSPECTED"), DENIED("DENIED"), APPROVED("APPROVED"), REVIEWING("REVIEWING"), UNVERIFIED("UNVERIFIED");

}
```

## Liveness Customization

The SDK provides additional liveness customization.

### 1. Creating IdenfyLivenessUIHelper

```kotlin theme={"system"}
    val idenfyLivenessUISettings: IdenfyLivenessUISettings = IdenfyLivenessUISettings()
```

### 2.1 Applying Regular Settings

If you only need color, text, or width customization, you can use properties from the `IdenfyLivenessUISettings` class:

```kotlin theme={"system"}
   class IdenfyLivenessUISettings() {

    //Liveness session feedback settings
    var livenessFeedbackBackgroundColor: Int? = null
    var livenessFeedbackFont: Typeface? = null

    //Liveness session frame settings
    var livenessFrameBackgroundColor: Int? = null
    var livenessFrameColor: Int? = null
    var livenessFrameWidth: Int? = null

    //Liveness session cancel button settings
    var livenessCancelButtonImage:Int?=null

    //Liveness session progress settings
    var livenessIdentificationOvalProgressColor1: Int? = null
    var livenessIdentificationOvalProgressColor2: Int? = null
    var livenessIdentificationProgressStrokeWidth: Int? = null
    var livenessIdentificationProgressRadialOffset: Int? = null
    var livenessIdentificationProgressStrokeColor: Int? = null

    //Liveness session overlay settings
    var livenessOverlayBrandingImage: Int? = null

    //Liveness ready screen settings
    var livenessReadyScreenForegroundColor: Int? = null
    var livenessReadyScreenBackgroundColor: Int? = null
    var livenessReadyScreenTextBackgroundColor: Int? = null
    var livenessReadyScreenButtonBorderColor: Int? = null
    var livenessReadyScreenButtonBorderWidth: Int? = null
    var livenessReadyScreenButtonCornerRadius: Int? = null
    var livenessReadyScreenButtonBackgroundNormalColor: Int? = null
    var livenessReadyScreenButtonBackgroundHighlightedColor: Int? = null
    var livenessReadyScreenButtonBackgroundDisabledColor: Int? = null
    var livenessReadyScreenShowBrandingImage: Boolean? = true

    //Camera Permission
    var livenessCameraPermissionsScreenImage:Int?=null

    //Liveness result screen settings
    var livenessResultScreenForegroundColor: Int? = null
    var livenessResultScreenIndicatorColor: Int? = null
    var livenessResultScreenUploadProgressFillColor: Int? = null
    var livenessResultScreenUploadProgressTrackColor: Int? = null
    var livenessResultScreenShowUploadProgressBar: Boolean? = true
    var livenessResultScreenResultAnimationSuccessBackgroundImage: Int? = null

    //Liveness id check customization
    var livenessIdCheckCustomization = LivenessIdCheckCustomization()

    //Full custom settings
    var livenessCustomUISettings: com.facetec.zoom.sdk.ZoomCustomization? = null
   }
```

**LivenessIdCheckCustomization:**

```kotlin theme={"system"}
class LivenessIdCheckCustomization() {
        var buttonBackgroundNormalColor: Int?=null
        var buttonBackgroundHighlightColor: Int?=null
        var captureScreenTextBackgroundColor: Int?=null
        var reviewScreenTextBackgroundColor: Int?=null
        var captureFrameStrokeColor: Int?=null
    }
```

### 2.2 Applying Full Customization

If you require more changes, you can directly set the **livenessCustomUISettings** property in `IdenfyLivenessUISettings` with your instance of the `FaceTecCustomization` class:

```kotlin theme={"system"}
    idenfyLivenessUISettings.livenessCustomUISettings = FaceTecCustomization()
```

Full customization options are available [here](https://dev.facetec.com/ui-customization).

<Note>
  This will override all other set properties of the IdenfyLivenessUISettings class.
</Note>

### 3. Updating IdenfyUISettings

```kotlin theme={"system"}
    val idenfyUISettingsV2 = IdenfyUISettingsV2.IdenfyUIBuilderV2()
        .withLivenessUISettings(idenfyLivenessUISettingsV2)
        ...
        build()
```
