UI Theme Customization
The Entrupy Android SDK uses Jetpack Compose for its UI and inherits colors and styles from your app's Material Theme. This allows you to align SDK screens with your application's branding without needing a separate theming API.
Overview
The SDK automatically picks up your app's Material 3 (or Material 2) theme. You customize the SDK's appearance by defining your theme in the standard Android way — through XML resources and/or Compose MaterialTheme.
The Entrupy logo is displayed on SDK screens as part of the branding policy. White-labeling is not permitted. Contact Entrupy for branding configuration details.
1. XML-Based Theme (Activity-Hosted SDK Screens)
SDK screens that launch as activities inherit from your app's XML theme. Define your theme in res/values/themes.xml:
<!-- res/values/themes.xml -->
<resources>
<style name="Theme.YourApp" parent="Theme.Material3.DayNight">
<item name="colorPrimary">@color/your_primary</item>
<item name="colorOnPrimary">@color/your_on_primary</item>
<item name="colorSecondary">@color/your_secondary</item>
<item name="colorOnSecondary">@color/your_on_secondary</item>
<item name="colorSurface">@color/your_surface</item>
<item name="colorOnSurface">@color/your_on_surface</item>
<item name="colorError">@color/your_error</item>
<item name="android:statusBarColor">@color/your_status_bar</item>
</style>
</resources>
Define your color palette in res/values/colors.xml:
<!-- res/values/colors.xml -->
<resources>
<color name="your_primary">#1976D2</color>
<color name="your_on_primary">#FFFFFF</color>
<color name="your_secondary">#FFC107</color>
<color name="your_on_secondary">#000000</color>
<color name="your_surface">#FFFFFF</color>
<color name="your_on_surface">#212121</color>
<color name="your_error">#D32F2F</color>
<color name="your_status_bar">#1565C0</color>
</resources>
2. Compose-Based Theme (Composable SDK Components)
SDK composables such as RegionPreferencesScreen and other SDK screens inherit from the nearest MaterialTheme in your Compose hierarchy:
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import com.entrupy.sdk.app.EntrupyApp
private val YourColorScheme = lightColorScheme(
primary = Color(0xFF1976D2),
onPrimary = Color.White,
secondary = Color(0xFFFFC107),
onSecondary = Color.Black,
surface = Color.White,
onSurface = Color(0xFF212121),
error = Color(0xFFD32F2F)
)
@Composable
fun MyApp() {
MaterialTheme(colorScheme = YourColorScheme) {
EntrupyApp.sharedInstance().RegionPreferencesScreen(onBack = { /* navigate back */ })
}
}
3. Dark Theme Support
For dark mode, define a night color resource file and the SDK adapts automatically:
<!-- res/values-night/colors.xml -->
<resources>
<color name="your_primary">#90CAF9</color>
<color name="your_on_primary">#000000</color>
<color name="your_surface">#121212</color>
<color name="your_on_surface">#FFFFFF</color>
</resources>
For Compose-based screens, provide a dark color scheme:
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
private val DarkColorScheme = darkColorScheme(
primary = Color(0xFF90CAF9),
onPrimary = Color.Black,
surface = Color(0xFF121212),
onSurface = Color.White
)
@Composable
fun ThemedEntrupyContent(content: @Composable () -> Unit) {
val colorScheme = if (isSystemInDarkTheme()) DarkColorScheme else YourColorScheme
MaterialTheme(colorScheme = colorScheme) {
content()
}
}
4. Embedding SDK Composables in Fragments and Activities
If your app uses Fragments or Activities with XML layouts (instead of full Compose), wrap SDK composables in a ComposeView:
Fragment Example
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.material3.MaterialTheme
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import com.entrupy.sdk.app.EntrupyApp
class RegionPreferencesFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return ComposeView(requireContext()).apply {
setContent {
MaterialTheme {
EntrupyApp.sharedInstance().RegionPreferencesScreen(onBack = { requireActivity().onBackPressedDispatcher.onBackPressed() })
}
}
}
}
}
Activity Example
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.MaterialTheme
import com.entrupy.sdk.app.EntrupyApp
class EntrupyActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
EntrupyApp.sharedInstance().RegionPreferencesScreen(onBack = { finish() })
}
}
}
}
System Bar Icon Style
By default, the SDK renders light (white) system bar icons (clock, battery, signal indicators), which suits the SDK's dark backgrounds. If your host app uses a light theme, you may want dark icons instead.
Use setStatusBarIconStyle to control the icon appearance across all SDK screens, including bottom sheets and modals:
import com.entrupy.sdk.app.EntrupyApp
import com.entrupy.sdk.model.StatusBarIconStyle
// Call before launching any SDK screen
val entrupyApp = EntrupyApp.sharedInstance()
// Light (white) icons — default, suitable for dark backgrounds
entrupyApp.setStatusBarIconStyle(StatusBarIconStyle.LIGHT)
// Dark (black) icons — suitable for light backgrounds
entrupyApp.setStatusBarIconStyle(StatusBarIconStyle.DARK)
| Value | Icon Color | Best For |
|---|---|---|
StatusBarIconStyle.LIGHT | White | Dark backgrounds (default) |
StatusBarIconStyle.DARK | Black | Light backgrounds |
Call setStatusBarIconStyle once during app initialization, before any call to startCapture(), displayDetailViewForItem(), or other SDK screen launchers. The setting persists for the lifetime of the process.
Dynamic Theme Updates
XML Layout with ComposeView
You can also add ComposeView directly in your XML layout:
<!-- res/layout/fragment_region.xml -->
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
import com.entrupy.sdk.app.EntrupyApp
class RegionPreferencesFragment : Fragment(R.layout.fragment_region) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<ComposeView>(R.id.compose_view).setContent {
MaterialTheme {
EntrupyApp.sharedInstance().RegionPreferencesScreen(onBack = { requireActivity().onBackPressedDispatcher.onBackPressed() })
}
}
}
}
Always wrap SDK composables in your app's MaterialTheme so they inherit your color scheme and typography. This applies to all SDK composables including RegionPreferencesScreen.
5. Runtime Theme Changes
Since SDK composables inherit from MaterialTheme, you can switch themes at runtime using Compose state. SDK screens update automatically:
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import com.entrupy.sdk.app.EntrupyApp
private val LightColors = lightColorScheme(
primary = Color(0xFF1976D2),
onPrimary = Color.White,
surface = Color.White,
onSurface = Color(0xFF212121)
)
private val DarkColors = darkColorScheme(
primary = Color(0xFF90CAF9),
onPrimary = Color.Black,
surface = Color(0xFF121212),
onSurface = Color.White
)
@Composable
fun ThemedApp() {
var isDarkTheme by remember { mutableStateOf(false) }
val colorScheme = if (isDarkTheme) DarkColors else LightColors
MaterialTheme(colorScheme = colorScheme) {
EntrupyApp.sharedInstance().RegionPreferencesScreen(onBack = { /* navigate back */ })
}
}
You can also create seasonal or brand-specific color schemes and swap them the same way — define multiple lightColorScheme() / darkColorScheme() instances and switch between them via state.
6. Accessibility Support
6.1 High Contrast Mode
The SDK respects the system's high contrast settings. To support users who enable high contrast, ensure your color scheme has strong contrast ratios:
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
private val HighContrastColors = lightColorScheme(
primary = Color(0xFF000000),
onPrimary = Color(0xFFFFFFFF),
surface = Color(0xFFFFFFFF),
onSurface = Color(0xFF000000),
error = Color(0xFFB00020),
onError = Color(0xFFFFFFFF)
)
6.2 Large Text and Font Scaling
The SDK respects the system font scale. SDK composables use Material Typography, which scales automatically with the user's accessibility settings. No additional configuration is needed.
If you provide custom typography, ensure it uses sp units (scalable pixels) so font scaling works:
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.sp
val AccessibleTypography = Typography(
bodyLarge = TextStyle(fontSize = 16.sp),
bodyMedium = TextStyle(fontSize = 14.sp),
labelLarge = TextStyle(fontSize = 14.sp)
)
@Composable
fun AccessibleEntrupyContent(content: @Composable () -> Unit) {
MaterialTheme(typography = AccessibleTypography) {
content()
}
}
6.3 Content Descriptions
SDK screens provide built-in content descriptions for screen readers (TalkBack). Interactive elements — buttons, images, form fields — include semantic descriptions for accessibility.
If you embed SDK composables inside your own UI, ensure your surrounding layout also follows accessibility best practices:
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
@Composable
fun AccessibleRegionView() {
Column {
Text(
text = "Region Preferences",
modifier = Modifier.semantics {
contentDescription = "Region preferences section"
}
)
EntrupyApp.sharedInstance().RegionPreferencesScreen(onBack = { /* navigate back */ })
}
}
7. Testing Theme Customization
7.1 Theme Preview
Use Jetpack Compose Preview to verify your theme with SDK composables before running on a device:
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
@Preview(name = "Light Theme", showBackground = true)
@Composable
fun PreviewLightTheme() {
MaterialTheme(colorScheme = LightColors) {
// Preview your themed layout here
// Note: SDK composables require initialization, so preview
// your theme wrapper without the SDK for visual verification
}
}
@Preview(name = "Dark Theme", showBackground = true, uiMode = android.content.res.Configuration.UI_MODE_NIGHT_YES)
@Composable
fun PreviewDarkTheme() {
MaterialTheme(colorScheme = DarkColors) {
// Preview dark theme layout
}
}
7.2 Theme Validation Checklist
Before publishing your themed integration, verify:
- Color contrast: Primary/onPrimary and surface/onSurface pairs meet WCAG AA minimum contrast ratio (4.5:1 for normal text, 3:1 for large text).
- Dark mode: All SDK screens are legible in both light and dark modes.
- Font scaling: Enable "Largest" font size in Android accessibility settings and verify SDK screens remain usable.
- Screen reader: Enable TalkBack and navigate through SDK screens to verify all interactive elements are announced.
- Orientation: Test SDK screens in both portrait and landscape.
8. Best Practices
- Apply your theme before SDK initialization. Ensure your
Applicationtheme is set in yourAndroidManifest.xmlbeforeEntrupyApp.init(this)is called. - Ensure adequate contrast. Test color combinations for readability, especially between primary/onPrimary and surface/onSurface pairs.
- Test in both light and dark modes. SDK screens should be legible in both configurations.
- Use Material 3 where possible. The SDK is built with Material 3 components for the best visual consistency.
- Wrap composables in MaterialTheme when embedding in Fragments or Activities via
ComposeView.
Next Steps
- Review the Capture Flow UI and Detail View Controller guides — primary composable surfaces that inherit your Compose theme, alongside
RegionPreferencesScreenand other SDK screens.