Skip to main content

UI Customization on Android

Introduction

Appearance for the UI elements provided by the SDK can be customized completely or partially by extending the default theme. Mind that it also supports dark mode and you have to override the values-night as well. Additionally, certain components offer complete appearance overrides, enabling you to detach their styles from the global appearance. While this approach requires more detailed configuration, it offers enhanced flexibility for creating unique designs.

Global theme customization

themes.xml
<resources>
<style name="Theme.MyApp" parent="Theme.PaysafeWallet">

<!-- typography -->
<item name="pswFontRegular">@font/regular</item>
<item name="pswFontLight">@font/light</item>
<item name="pswFontSemibold">@font/semibold</item>

<!-- corner radius -->
<item name="pswCornerRadiusSmall">2dp</item>
<item name="pswCornerRadiusMedium">4dp</item>
<item name="pswCornerRadiusLarge">8dp</item>

<!-- border stroke width -->
<item name="pswBorderStrokeWidth">1dp</item>

<!-- drawables -->
<item name="pswIconClose">@drawable/ic_close_template</item>
<item name="pswIconErrorTriangle">@drawable/ic_error_triangle_template</item>
<item name="pswIconInfo">@drawable/ic_ui_info_template</item>
<item name="pswSelectorDrawableCheckbox">@drawable/bg_checkbox</item>

<!-- base app background color. -->
<item name="pswColorBaseDefault">#F8F8F8</item>

<!-- surface background color over the base. -->
<item name="pswColorSurfaceDefault">#0D141414</item>
<item name="pswColorSurfaceElevated">#FFFFFF</item>
<item name="pswColorSurfaceDisabled">#0D141414</item>
<item name="pswColorSurfaceFocused">#14141414</item>
<item name="pswColorSurfacePressed">#1F141414</item>

<!-- text color. -->
<item name="pswColorTextPrimary">#141414</item>
<item name="pswColorTextPrimaryInverted">#F5F5F5</item>
<item name="pswColorTextSecondary">#424542</item>
<item name="pswColorTextSecondaryInverted">#C9CAC8</item>
<item name="pswColorTextActive">#054AB2</item>
<item name="pswColorTextActiveInverted">#B1D2FF</item>
<item name="pswColorTextPressed">#0860E3</item>
<item name="pswColorTextFocused">#003F9D</item>
<item name="pswColorTextDisabled">#787D78</item>
<item name="pswColorTextDisabledInverted">#B1B2AF</item>

<!-- all graphic elements that are clickable - buttons. icons, parts of atoms. etc. Do not use for active text! -->
<item name="pswColorActionActive">#0455CD</item>
<item name="pswColorActionSupportiveActive">#4771ED</item>
<item name="pswColorActionPressed">#0860E3</item>
<item name="pswColorActionSelected">#E2ECF9</item>
<item name="pswColorActionFocused">#003F9D</item>
<item name="pswColorActionActiveInverted">#B1D2FF</item>
<item name="pswColorActionInactive">#2C2E2C</item>
<item name="pswColorActionInactiveSubtle">#5F615D</item>
<item name="pswColorActionDisabled">#969896</item>
<item name="pswColorActionDisabledSubtle">#C9CAC8</item>

<!-- icons and visual indicative elements. Can be clickable. but only when used for special occasions. -->
<item name="pswColorContentInformativeIntense">#004370</item>
<item name="pswColorContentInformative">#075BC3</item>
<item name="pswColorContentInformativeSubtle">#66C0ECFA</item>
<item name="pswColorContentPositiveIntense">#005C20</item>
<item name="pswColorContentPositive">#179743</item>
<item name="pswColorContentPositiveSubtle">#66BCF1AC</item>
<item name="pswColorContentAttentionIntense">#934A00</item>
<item name="pswColorContentAttention">#D66000</item>
<item name="pswColorContentAttentionSubtle">#66FFE8A6</item>
<item name="pswColorContentNegativeIntense">#990D00</item>
<item name="pswColorContentNegative">#D31D33</item>
<item name="pswColorContentNegativeSubtle">#66FFA5A5</item>
<item name="pswColorContentBrandPrimaryIntense">#003F9D</item>
<item name="pswColorContentBrandPrimary">#0455CD</item>
<item name="pswColorContentBrandPrimarySubtle">#4DF492F7</item>
<item name="pswColorContentBrandSecondaryIntense">#076580</item>
<item name="pswColorContentBrandSecondary">#1CB535</item>
<item name="pswColorContentBrandSecondarySubtle">#4DBAF1BF</item>
<item name="pswColorContentBrandAccent">#FCE72C</item>
<item name="pswColorContentBrandAccentModerate">#FFF681</item>
<item name="pswColorContentBrandAccentSubtle">#FFFCD9</item>
<item name="pswColorContentElementIntense">#61141414</item>
<item name="pswColorContentSeparator">#C9CAC8</item>
<item name="pswColorContentBlack">#141414</item>
<item name="pswColorContentBlackSubtle">#61141414</item>
<item name="pswColorContentWhite">#F5F5F5</item>
</style>
</resources>

Customize individual components

Certain components offer complete appearance overrides, enabling you to detach their styles from the global appearance. Here's how you configure individual components style configurations:

InputView

The InputView consists of an EditText and an InputFieldStyle wrapping it. You can configure them like so:

styles.xml
<resources>
<style name="Widget.MyApp.EditText" parent="Widget.PaysafeCoreComponents.EditText">
<item name="android:textAppearance">@style/MyStyle</item>
<item name="android:paddingTop">20dp</item>
<item name="android:paddingBottom">10dp</item>
<item name="android:textColor">@color/my_color</item>
</style>

<style name="Widget.MyApp.Input" parent="Widget.PaysafeCoreComponents.Input">
<item name="theme">@style/MyStyle</item>

<item name="boxBackgroundColor">@color/my_color</item>
<item name="boxStrokeWidth">1dp</item>
<item name="boxStrokeWidthFocused">1dp</item>
<item name="boxStrokeErrorColor">@color/my_box_stroker_error_color</item>
<item name="boxCornerRadiusTopStart">2dp</item>
<item name="boxCornerRadiusTopEnd">2dp</item>
<item name="boxCornerRadiusBottomStart">2dp</item>
<item name="boxCornerRadiusBottomEnd">2dp</item>
<item name="boxCollapsedPaddingTop">8dp</item>

<item name="startIconTint">@color/start_icont_tint_color</item>
<item name="startIconMinSize">24dp</item>
<item name="endIconTint">@color/end_icon_tint_color</item>
<item name="endIconMinSize">24dp</item>

<item name="hintTextAppearance">@style/hint_text_appearance</item>
<item name="hintTextColor">@color/hint_text_color</item>

<item name="helperTextTextAppearance">@style/helper_text_appearance</item>
<item name="helperTextTextColor">@color/helper_text_color</item>

<item name="errorTextAppearance">@style/error_text_appearance</item>
<item name="errorTextColor">@color/error_text_color</item>
<item name="errorIconDrawable">@null</item>
</style>

</resources>

After declaring your styles for this component, you need to override an attribute responsible for setting your style.

themes.xml
<resources>

<style name="Theme.MyApp" parent="Theme.PaysafeWallet">
<item name="pswInputFieldStyle">@style/Widget.MyApp.Input</item>
<item name="pswEditTextStyle">@style/Widget.MyApp.EditText</item>
</style>

</resources>

Button

There are 3 button types that you may override:

  • Primary
  • Secondary
  • Text

To give a unique appearance to each one of them and detach them from the theme, you may follow a similar to the InputView approach.

styles.xml
<resources>
<style name="Widget.MyApp.Button.Primary" parent="Widget.PaysafeCoreComponents.Button.Primary">
<item name="android:paddingTop">8dp</item>
<item name="android:paddingRight">8dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:paddingLeft">8dp</item>
<item name="android:minHeight">40dp</item>
<item name="android:minWidth">0dp</item>
<item name="android:theme">@style/MyButtonTheme</item>
<item name="android:textAppearance">@style/MyTextStyle</item>
<item name="backgroundTint">@color/my_button_background_color_tint</item>
<item name="android:textColor">@color/my_button_text_color</item>
<item name="cornerRadius">8dp</item>
<item name="rippleColor">@color/my_button_ripple_color</item>
<item name="pswButtonLoadingColor">@color/my_button_loading_color</item>
</style>

<style name="Widget.MyApp.Button.Secondary" parent="Widget.PaysafeCoreComponents.Button.Secondary">
<item name="android:paddingTop"><8dp/item>
<item name="android:paddingRight">8dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:paddingLeft">8dp</item>
<item name="android:minHeight">40dp</item>
<item name="android:minWidth">0dp</item>
<item name="android:theme">@style/MyButtonTheme</item>
<item name="android:textAppearance">@style/MyTextStyle</item>
<item name="android:textColor">@color/my_button_text_color</item>
<item name="cornerRadius">8dp</item>
<item name="rippleColor">@color/my_button_ripple_color</item>
<item name="pswButtonLoadingColor">@color/my_button_loading_color</item>
<item name="strokeWidth">2dp</item>
<item name="strokeColor">@color/my_stroke_color</item>
</style>

<style name="Widget.MyApp.Button.Text" parent="Widget.PaysafeCoreComponents.Button.Text">
<item name="android:paddingTop"><8dp/item>
<item name="android:paddingRight">8dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:paddingLeft">8dp</item>
<item name="android:minHeight">40dp</item>
<item name="android:minWidth">0dp</item>
<item name="android:theme">@style/MyButtonTheme</item>
<item name="android:textAppearance">@style/MyTextStyle</item>
<item name="android:textColor">@color/my_button_text_color</item>
<item name="cornerRadius">8dp</item>
<item name="rippleColor">@color/my_button_ripple_color</item>
<item name="pswButtonLoadingColor">@color/my_button_loading_color</item>
</style>

<style name="MyButtonStyle" parent="ThemeOverlay.PaysafeCoreComponents.Button.Primary">
<item name="colorPrimary">@color/my_primary_color</item>
<item name="colorPrimaryDark">@color/my_primary_dark_color</item>
<item name="colorOnPrimary">@color/my_color_on_primary</item>
</style>
</resources>
themes.xml
<resources>

<style name="Theme.MyApp" parent="Theme.PaysafeWallet">
<item name="pswPrimaryButtonStyle">@style/Widget.MyApp.Button.Primary</item>
<item name="pswSecondaryButtonStyle">@style/Widget.MyApp.Button.Secondary</item>
<item name="pswTextButtonStyle">@style/Widget.MyApp.Button.Text</item>
</style>

</resources>

Checkbox

The checkbox component also allows a customization above what the theme customization has to offer. Here's an example of how to achieve this:

styles.xml
<resources>

<style name="ThemeOverlay.MyApp.CheckBoxStyle" parent="ThemeOverlay.PaysafeCoreComponents.CheckBoxStyle">
<item name="checkboxTint">@color/my_checkbox_tint_color</item>
<item name="checkboxBackground">@drawable/checkbox_ripple</item>
</style>

</resources>
drawable/checkbox_ripple.xml

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/checkbox_ripple_colors"
android:radius="20dp" />

drawable/checkbox_look.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/my_checkbox_look_when_unchecked" android:state_checked="false" />
<item android:drawable="@drawable/my_checkbox_look_when_checked" android:state_checked="true" />
</selector>
color/checkbox_ripple_colors.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/color_not_checked" android:state_checked="false" android:state_enabled="true" />
<item android:color="@color/color_checked" android:state_checked="true" android:state_enabled="true" />
</selector>

themes.xml

<resources>

<style name="Theme.MyApp" parent="Theme.PaysafeWallet">
<item name="pswSelectorDrawableCheckbox">@drawable/checkbox_look <!-- may be an X mark for example --> </item>
<item name="pswCheckboxStyle">@style/ThemeOverlay.MyApp.CheckboxStyle</item>
</style>

</resources>

LinksLabel component

The LinksLabel may be a simple text or a text containing an emphasis(typically a link). As the other components, it has default colors for both, but can be overriden specifically for this component:

styles.xml

<style name="ThemeOverlay.MyApp.LinksLabelViewStyle" parent="ThemeOverlay.PaysafeCoreComponents.LinksLabelStyle">
<item name="linksLabelTextColor">@color/main_text_color</item>
<item name="linksLabelClickablePartColor">@color/emphasis_text_color</item>
</style>

themes.xml

<resources>
<style name="Theme.MyApp" parent="Theme.PaysafeWallet">

<item name="pswLinksLabelStyle">@style/ThemeOverlay.MyApp.LinksLabelViewStyle</item>

</style>
</resources>
note

It is recommended that you only override the Global theme customization, shown here. This way, you'll ensure that your app experience will be the same in every flow. Having a semantic color palette will maintain consistency and ensure accessibility across the product's visual identity. However, you may give a unique look to the components mentioned above, following the examples.

Configuring the SDK with a custom theme

Specify the newly created theme Theme.MyApp in the initial SDK configuration:

wallet.configure(
SdkConfiguration(
configToken = "<config-token>",
apiEnvironment = ApiEnvironment.Production,
context = this@MainActivity,
customThemeResId = R.style.Theme_MyApp
)
)

The customThemeResId field in the SdkConfiguration object is optional. If not provided, a default theme will be used.