Styling & Theming

Android SDK: Styling & Theming

Customize colors, typography, spacing, and component styles throughout the Digital Card Engine UI SDK using the centralized StyleConfiguration system.

Prerequisites:

  • SDK initialized with DigitalCardEngineSDK.initialize(...)
  • Access to the sdk.styleConfiguration instance

StyleConfiguration Overview

The SDK uses a single mutable StyleConfiguration object that controls the visual appearance of all UI components. This matches the iOS SDK design for cross-platform consistency.

val sdk = DigitalCardEngineSDK()
// After initialization, customize appearance
sdk.styleConfiguration.palette.secondary = Color(0xFFFF5722)
sdk.styleConfiguration.spacing = 12f
sdk.styleConfiguration.currencySymbol = "$"

Palette (Color System)

The Palette defines semantic colors used throughout the SDK. All colors follow Material Design 3 naming conventions and match iOS exactly.

data class Palette(
    var surface: Color = Color(0xFFFFFFFF),              // Backgrounds
    var onSurface: Color = Color(0xFF1C1B1B),            // Primary text
    var onSurfaceVariant: Color = Color(0xFF5C5F66),     // Secondary text
    var secondary: Color = Color(0xFF2353C8),            // Brand/accent
    var tertiary: Color = Color(0xFF4CAF50),             // Success/positive
    var outlineVariant: Color = Color(0xFFE4E6EB),       // Borders/dividers
    var surfaceContainerHighest: Color = Color(0xFFE0E3E8) // Subtle backgrounds
)

Color Usage Guide

ColorDefaultUsage
surface#FFFFFFCard backgrounds, container surfaces
onSurface#1C1B1BPrimary text (titles, card labels)
onSurfaceVariant#5C5F66Secondary text (subtitles, metadata)
secondary#2353C8Action buttons, brand elements
tertiary#4CAF50Positive amounts, success indicators
outlineVariant#E4E6EBDividers, borders, separators
surfaceContainerHighest#E0E3E8Card backgrounds when stacked

Customizing Colors

// Apply your brand colors
sdk.styleConfiguration.palette = StyleConfiguration.Palette(
    surface = Color.White,
    onSurface = Color(0xFF1A1A1A),
    onSurfaceVariant = Color(0xFF666666),
    secondary = Color(0xFF00A86B),        // Your brand color
    tertiary = Color(0xFF4CAF50),
    outlineVariant = Color(0xFFE0E0E0),
    surfaceContainerHighest = Color(0xFFF5F5F5)
)

Typography (Fonts & TypeScale)

The SDK uses Material Design 3 typography scales. Each scale has a regular and emphasized (bold) variant.

data class Fonts(
    var titleLarge: TypeScale,
    var titleMedium: TypeScale,
    var titleSmall: TypeScale,
    var labelLarge: TypeScale,
    var labelMedium: TypeScale,
    var labelSmall: TypeScale,
    var bodyLarge: TypeScale,
    var bodyMedium: TypeScale,
    var bodySmall: TypeScale
)

data class TypeScale(
    var textStyle: TextStyle,          // Regular weight
    var textStyleEmphasized: TextStyle // Bold/emphasized weight
)

Typography Scale Reference

ScaleSizeLetter SpacingUsage
titleLarge22sp0spScreen titles, large headings
titleMedium16sp0.15spSection titles, card titles
titleSmall14sp0.1spSmall headings, labels
labelLarge14sp0.1spButton text, prominent labels
labelMedium12sp0.5spInput labels, metadata
labelSmall11sp0.5spCaptions, small metadata
bodyLarge16sp0.5spPrimary body text
bodyMedium14sp0.25spSecondary body text
bodySmall12sp0.4spSmall body text, footnotes

Custom Typography

import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp

// Apply custom font family
val customFonts = Fonts(
    titleLarge = TypeScale(
        textStyle = TextStyle(
            fontFamily = FontFamily.SansSerif,
            fontWeight = FontWeight.Normal,
            fontSize = 22.sp,
            letterSpacing = 0.sp
        ),
        textStyleEmphasized = TextStyle(
            fontFamily = FontFamily.SansSerif,
            fontWeight = FontWeight.Bold,
            fontSize = 22.sp,
            letterSpacing = 0.sp
        )
    ),
    // ... customize other scales
)

sdk.styleConfiguration.fonts = customFonts

Using Custom Font Families

import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight

val MyFontFamily = FontFamily(
    Font(R.font.my_font_regular, FontWeight.Normal),
    Font(R.font.my_font_medium, FontWeight.Medium),
    Font(R.font.my_font_bold, FontWeight.Bold)
)

sdk.styleConfiguration.fonts.bodyMedium = TypeScale(
    textStyle = TextStyle(
        fontFamily = MyFontFamily,
        fontWeight = FontWeight.Normal,
        fontSize = 14.sp
    ),
    textStyleEmphasized = TextStyle(
        fontFamily = MyFontFamily,
        fontWeight = FontWeight.Bold,
        fontSize = 14.sp
    )
)

Component-Specific Properties

CardListViewProperties

Control card list behavior and layout.

data class CardListViewProperties(
    var title: Boolean = true,                           // Show "My Cards" header
    var actionButton: Boolean = true,                    // Show "Add Card" button
    var dividers: Boolean = true,                        // Show separators
    var cardListStyle: CardListViewStyle = LargeStyle    // Layout density
)

enum class CardListViewStyle {
    DefaultStyle,  // Compact rows for dashboards
    LargeStyle     // Spacious cards (default)
}

Usage:

sdk.styleConfiguration.cardListViewProperties = CardListViewProperties(
    title = false,
    actionButton = true,
    dividers = true,
    cardListStyle = CardListViewStyle.DefaultStyle
)

CardDetailsViewProperties

Control card details screen behavior.

data class CardDetailsViewProperties(
    var actionButton: Boolean = true,                    // Show action buttons
    var slider: Boolean = false,                         // Enable card slider
    var cardInfoStyle: CardDetailsViewStyle = DetailStyle, // Info density
    var useFetchedImages: Boolean = false                // Use fetched card art
)

enum class CardDetailsViewStyle {
    BriefStyle,    // Compact info
    DetailStyle    // Full details (default)
}

Usage:

sdk.styleConfiguration.cardDetailsViewProperties = CardDetailsViewProperties(
    actionButton = true,
    slider = true,
    cardInfoStyle = CardDetailsViewStyle.DetailStyle,
    useFetchedImages = true
)

Spacing

Global spacing multiplier applied to paddings and gaps throughout the SDK.

// Default is 8dp
sdk.styleConfiguration.spacing = 12f  // Increase spacing
sdk.styleConfiguration.spacing = 4f   // Decrease spacing

Currency Symbol

Set the currency symbol displayed with monetary amounts.

sdk.styleConfiguration.currencySymbol = "$"   // US Dollar
sdk.styleConfiguration.currencySymbol = "€"   // Euro
sdk.styleConfiguration.currencySymbol = "R"   // South African Rand
sdk.styleConfiguration.currencySymbol = "£"   // British Pound

Applying Styles to Components

Global Application (Recommended)

Apply styles once at app initialization:

class MyApp : Application() {
    lateinit var sdk: DigitalCardEngineSDK
    
    override fun onCreate() {
        super.onCreate()
        
        sdk = DigitalCardEngineSDK()
        sdk.initialize(/* ... */)
        
        // Apply global theme
        applyCustomTheme(sdk.styleConfiguration)
    }
    
    private fun applyCustomTheme(config: StyleConfiguration) {
        config.palette = Palette(
            secondary = Color(0xFF00A86B),
            tertiary = Color(0xFF4CAF50)
        )
        config.currencySymbol = "$"
        config.spacing = 12f
    }
}

Per-Screen Customization

Use CompositionLocalProvider to apply custom styles to specific screens:

import androidx.compose.runtime.CompositionLocalProvider
import com.paymentology.digital_card_engine_sdk_android.ui.theme.LocalStyleConfiguration

@Composable
fun CustomStyledCardList(sdk: DigitalCardEngineSDK) {
    val customConfig = StyleConfiguration().apply {
        palette = Palette(secondary = Color(0xFFFF5722))
    }
    
    CompositionLocalProvider(LocalStyleConfiguration provides customConfig) {
        UILibrary.CardListView(
            sdk = sdk,
            onCardSelected = { /* ... */ }
        )
    }
}

Component-Level Styling

Pass style properties directly to individual components:

import com.paymentology.digital_card_engine_sdk_android.ui.*

@Composable
fun CustomizedCardOverview(card: CardEntity, sdk: DigitalCardEngineSDK) {
    UILibrary.CardOverview(
        card = card,
        properties = CardOverviewProperties(
            cardInfo = CardInfo.Detail,
            actionButton = true,
            cardWidgetStyle = CardWidgetStyle.Large
        ),
        style = CardOverviewStyleProperties(
            externalPadding = 24f,
            internalHorizontalPadding = 20f,
            internalVerticalPadding = 16f,
            radius = 16f
        ),
        sdk = sdk
    )
}

Style Properties Reference

CardListViewStyleProperties

data class CardListViewStyleProperties(
    var internalHorizontalPadding: Float = 16f,  // Card content horizontal padding
    var internalVerticalPadding: Float = 12f,    // Card content vertical padding
    var externalPadding: Float = 16f,            // List container padding
    var internalGap: Float = 16f,                // Spacing between cards
    var radius: Float = 12f                      // Card corner radius
)

CardOverviewStyleProperties

data class CardOverviewStyleProperties(
    var externalPadding: Float = 16f,            // Container padding
    var internalHorizontalPadding: Float = 16f,  // Content horizontal padding
    var internalVerticalPadding: Float = 16f,    // Content vertical padding
    var radius: Float = 16f,                     // Corner radius
    var titleTextStyle: TextStyle? = null,       // Optional title override
    var balanceTextStyle: TextStyle? = null      // Optional balance override
)

TransactionsCardStyleProperties

data class TransactionsCardStyleProperties(
    var externalPadding: Float = 16f,
    var internalHorizontalPadding: Float = 16f,
    var internalVerticalPadding: Float = 12f,
    var internalGap: Float = 12f,
    var radius: Float = 12f
)

Best Practices

  1. Apply globally: Set styles once at app startup via sdk.styleConfiguration
  2. Use semantic colors: Leverage the Palette system rather than hardcoding colors
  3. Maintain consistency: Keep spacing and typography consistent across screens
  4. Test accessibility: Ensure text contrasts meet WCAG standards
  5. Avoid per-component overrides: Only override when absolutely necessary
  6. Document custom themes: Keep a reference of your color/font choices

Complete Example

import android.app.Application
import androidx.compose.ui.graphics.Color
import com.paymentology.digital_card_engine_sdk_android.DigitalCardEngineSDK
import com.paymentology.digital_card_engine_sdk_android.ui.*

class MyApp : Application() {
    lateinit var sdk: DigitalCardEngineSDK
    
    override fun onCreate() {
        super.onCreate()
        
        sdk = DigitalCardEngineSDK()
        sdk.initialize(/* ... */)
        
        // Apply comprehensive theme
        with(sdk.styleConfiguration) {
            // Colors
            palette = Palette(
                surface = Color.White,
                onSurface = Color(0xFF1A1A1A),
                onSurfaceVariant = Color(0xFF666666),
                secondary = Color(0xFF00A86B),
                tertiary = Color(0xFF4CAF50),
                outlineVariant = Color(0xFFE0E0E0),
                surfaceContainerHighest = Color(0xFFF5F5F5)
            )
            
            // Global settings
            spacing = 12f
            currencySymbol = "$"
            
            // Card list preferences
            cardListViewProperties = CardListViewProperties(
                title = true,
                actionButton = true,
                dividers = true,
                cardListStyle = CardListViewStyle.LargeStyle
            )
            
            // Card details preferences
            cardDetailsViewProperties = CardDetailsViewProperties(
                actionButton = true,
                slider = false,
                cardInfoStyle = CardDetailsViewStyle.DetailStyle,
                useFetchedImages = true
            )
        }
    }
}

Troubleshooting

Styles not applying: Ensure you modify sdk.styleConfiguration after initialize() but before rendering UI components.

Colors look wrong: Verify you're using Color(0xFFRRGGBB) format with the alpha channel (FF).

Fonts not loading: Check that custom font resources are in res/font/ and properly referenced in FontFamily.

Per-screen styles not working: Ensure CompositionLocalProvider wraps the component tree where custom styles should apply.