Theming the SDK screens
The ui module ships ready-made screens — currently the Wearing Optimization flow. They are drawn with the SDK's own palette so they stay readable inside any host app, and every colour and style they use can be replaced by your app.
implementation "com.corsano.sdk:ui:$corsanoSdkVersion"
Re-skinning the flow takes no code inside the screens: pin the palette if you need to, then redeclare the resources you want to change.
Light and dark mode
The SDK ships two palettes, light and dark. Which one applies is decided by the system UI mode, exactly like any Android resource — not by your app's theme.
Warning: An app that only has a light theme, but does not opt out of night mode, still gets the dark SDK palette as soon as the phone is switched to dark mode. This is the usual cause of unreadable SDK screens.
There are two ways to opt out. App-wide:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
Or, if your app cannot or does not want to change its own night-mode handling, for the SDK screens only:
CorsanoUiTheme.nightMode = CorsanoUiTheme.NightMode.LIGHT
Both are supported. CorsanoUiTheme.nightMode affects only the SDK screens and their dialogs, and leaves the rest of your app alone.
CorsanoUiTheme
object CorsanoUiTheme — the theming entry point.
| Member | Type | Description |
|---|---|---|
nightMode | NightMode | Which palette the SDK screens use. Defaults to FOLLOW_SYSTEM |
wrap(context) | Context | Returns a context resolving resources with the UI mode forced to nightMode |
wrap(inflater) | LayoutInflater | The same, applied to a LayoutInflater |
enum class NightMode {
FOLLOW_SYSTEM, // default: follow the system dark mode setting
LIGHT, // always the light palette
DARK // always the dark palette
}
Set it once, before any SDK screen is opened — Application.onCreate() is the natural place:
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
CorsanoSdk.initialize(this, config)
// The SDK screens stay light even when the phone is switched to dark mode.
CorsanoUiTheme.nightMode = CorsanoUiTheme.NightMode.LIGHT
}
}
Note:
wrap()is only needed if you host SDK views yourself. The shipped screens call it internally. WhennightModeisFOLLOW_SYSTEM,wrap()returns the context unchanged.
Colours
Declaring a colour with the same name in your app module replaces the SDK one, throughout the whole flow. Put it in any file under res/values/ — the file name does not matter, only the resource names do. Add a res/values-night/ variant too if your app supports dark mode.
| Resource | Used for |
|---|---|
colorAppBar | Main accent: filled buttons, progress bar, image borders, links |
colorAppBarText | Text drawn on colorAppBar (filled buttons) |
mainBackground | Background of the screens |
main_background_opacity_12 | Cards and other raised blocks, disabled button background |
text_high_emphasis | Titles, values, icons |
text_medium_emphasis | Descriptions |
text_disable_emphasis | Disabled text |
error | Error state: mandatory field not filled, wrong wearing instruction |
colorGreenOk / wearing_opt_instruction_ok_color | Correct wearing instruction |
menuArrow | Chevron of the selectable rows |
skin_type_fitzpatrick_1 … _6 | Skin-type picker swatches |
Warning:
mainBackgroundand thetext_*colours are a set. Overriding one without the others can leave text unreadable — for example dark text on a dark background.
Styles
Same principle: redeclaring a style with the same name in your app module replaces the SDK one.
| Style | Used for |
|---|---|
ConfirmButton | Primary button (Next, Confirm) |
SecondaryButton | Secondary button (Back) |
TextLinkButton | Inline link-like button |
ProgressBarTheme | Horizontal progress bar of the flow |
RoundedImage | Corner shape of the illustrations |
TextAdaptable | Auto-sizing labels of the selectable rows |
Warning: An overriding style replaces the SDK one entirely — it does not merge. Repeat every item you want to keep.
The buttons take their enabled and disabled colours from the colour state lists confirm_button_background_tint, confirm_button_text and secondary_button_text, which are themselves built from the palette above. Overriding colorAppBar, colorAppBarText and text_disable_emphasis is usually enough, without touching the styles at all.
Worked example: a light-only app
An app with a single light theme that wants the SDK flow in its own brand colours. Two steps.
1. Pin the palette, once, before any SDK screen is opened:
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
CorsanoSdk.initialize(this, config)
CorsanoUiTheme.nightMode = CorsanoUiTheme.NightMode.LIGHT
}
}
2. Override the palette in your app module:
<!-- app/src/main/res/values/colors_corsano_sdk.xml -->
<resources>
<!-- Accent: filled buttons, progress bar, links, image borders -->
<color name="colorAppBar">#0B4F6C</color>
<color name="colorAppBarText">#FFFFFF</color>
<!-- Surfaces and text, to keep as one consistent set -->
<color name="mainBackground">#FFFFFF</color>
<color name="main_background_opacity_12">#14000000</color>
<color name="text_high_emphasis">#DE000000</color>
<color name="text_medium_emphasis">#99000000</color>
<color name="text_disable_emphasis">#61000000</color>
<!-- States -->
<color name="error">#C62828</color>
<color name="colorGreenOk">#2E7D32</color>
</resources>
That covers the whole flow: buttons, progress bar, cards, titles, descriptions, the red highlight of a missing wrist or skin type, and the wearing instructions all follow from these.
Because night mode is pinned to LIGHT, a values-night/ variant is not needed. Add one only if the app later supports dark mode and switches back to FOLLOW_SYSTEM.
Changing the button shape
<!-- app/src/main/res/values/styles_corsano_sdk.xml -->
<resources>
<style name="ConfirmButton" parent="Widget.MaterialComponents.Button">
<item name="android:textAllCaps">false</item>
<item name="android:textSize">15sp</item>
<item name="android:minHeight">48dp</item>
<item name="cornerRadius">24dp</item> <!-- pill shaped -->
<item name="backgroundTint">@color/confirm_button_background_tint</item>
<item name="android:textColor">@color/confirm_button_text</item>
</style>
</resources>
Warning: Keep
backgroundTintandandroid:textColorpointing at the SDK colour state lists. They preserve the disabled state — the Next button on the confirm-setup page is disabled until wrist and skin type are filled in, and a flat colour there makes a disabled button look enabled.
Host app requirements
The SDK screens are hosted in your own activity, so your app theme still supplies the ripples, dialogs and text appearances. A Theme.MaterialComponents.* or Theme.Material3.* theme is expected.