Skip to main content
SystemBars allows you to configure the appearance of Android’s status bar and navigation bar, including their colors and content appearance. It enables edge-to-edge display with proper system bar styling.
SystemBars is Android-specific and currently only works on Android platforms. On other platforms, this component has no effect.

Usage

import com.nomanr.lumo.ui.components.native.SystemBars
import com.nomanr.lumo.ui.components.native.SystemBarsDefaults

@Composable
fun App() {
    AppTheme {
        SystemBars(
            colors = SystemBarsDefaults.defaultColors()
        )
        
        // Your app content
        MyAppContent()
    }
}

Default Colors

Use theme-based default colors:
SystemBars(
    colors = SystemBarsDefaults.defaultColors()
    // Status bar: primary color
    // Navigation bar: background color
)

Custom Colors

Set specific colors for status and navigation bars:
SystemBars(
    colors = SystemBarColor(
        statusBarColor = AppTheme.colors.primary,
        navigationBarColor = AppTheme.colors.surface
    )
)

Edge-to-Edge Display

SystemBars automatically enables edge-to-edge mode, making system bars transparent while adjusting the content color based on the provided colors:
@Composable
fun EdgeToEdgeApp() {
    AppTheme {
        // System bars become transparent
        SystemBars(
            colors = SystemBarColor(
                statusBarColor = AppTheme.colors.background,
                navigationBarColor = AppTheme.colors.background
            )
        )
        
        Scaffold(
            modifier = Modifier
                .fillMaxSize()
                // Content extends behind system bars
                .systemBarsPadding() // Add padding to avoid overlap
        ) {
            // Your content
        }
    }
}

Dynamic Colors

Change system bar colors based on scroll position or screen:
@Composable
fun DynamicSystemBars() {
    var isScrolled by remember { mutableStateOf(false) }
    
    SystemBars(
        colors = SystemBarColor(
            statusBarColor = if (isScrolled) {
                AppTheme.colors.surface
            } else {
                AppTheme.colors.primary
            },
            navigationBarColor = AppTheme.colors.background
        )
    )
    
    LazyColumn(
        modifier = Modifier.fillMaxSize()
    ) {
        // Detect scroll and update isScrolled
    }
}

Parameters

SystemBars

colors
SystemBarColor
required
Configuration for system bar colors

SystemBarColor

statusBarColor
Color
required
Color used to determine status bar appearance (not the actual bar color in edge-to-edge mode)
navigationBarColor
Color
required
Color used to determine navigation bar appearance (not the actual bar color in edge-to-edge mode)

SystemBarsDefaults

defaultColors()
@Composable () -> SystemBarColor
Returns default system bar colors using theme colors
colors(isStatusContentBarDark: Boolean, isNavigationContentBarDark: Boolean)
@Composable (Boolean, Boolean) -> SystemBarColor
Returns system bar colors based on content darkness

Content Appearance

The system automatically determines whether to use light or dark icons:
// Light icons on dark backgrounds
SystemBars(
    colors = SystemBarColor(
        statusBarColor = Color.Black, // Light icons
        navigationBarColor = Color.DarkGray // Light icons
    )
)

// Dark icons on light backgrounds
SystemBars(
    colors = SystemBarColor(
        statusBarColor = Color.White, // Dark icons
        navigationBarColor = Color.LightGray // Dark icons
    )
)
The component calculates luminance and chooses appropriate icon colors:
  • Luminance < 0.5 → Light icons
  • Luminance ≥ 0.5 → Dark icons

Screen-Specific Colors

@Composable
fun HomeScreen() {
    SystemBars(
        colors = SystemBarColor(
            statusBarColor = AppTheme.colors.primary,
            navigationBarColor = AppTheme.colors.background
        )
    )
    // Home content
}

@Composable
fun SettingsScreen() {
    SystemBars(
        colors = SystemBarColor(
            statusBarColor = AppTheme.colors.surface,
            navigationBarColor = AppTheme.colors.surface
        )
    )
    // Settings content
}

With Scaffold

@Composable
fun AppWithScaffold() {
    SystemBars(
        colors = SystemBarsDefaults.defaultColors()
    )
    
    Scaffold(
        topBar = {
            TopBar(
                title = { Text("My App") },
                backgroundColor = AppTheme.colors.primary
            )
        },
        bottomBar = {
            NavigationBar {
                // Navigation items
            }
        }
    ) { paddingValues ->
        Box(modifier = Modifier.padding(paddingValues)) {
            // Content
        }
    }
}

Transparent Bars

For immersive experiences:
@Composable
fun ImmersiveScreen() {
    // Determine bar colors from content
    val topContentColor = AppTheme.colors.background
    val bottomContentColor = AppTheme.colors.surface
    
    SystemBars(
        colors = SystemBarColor(
            statusBarColor = topContentColor,
            navigationBarColor = bottomContentColor
        )
    )
    
    Box(modifier = Modifier.fillMaxSize()) {
        // Full-screen image or video
        Image(
            painter = painterResource("background.jpg"),
            contentDescription = null,
            modifier = Modifier.fillMaxSize(),
            contentScale = ContentScale.Crop
        )
        
        // Content with proper padding
        Column(
            modifier = Modifier
                .fillMaxSize()
                .systemBarsPadding()
        ) {
            // Your content
        }
    }
}

Dark Mode Support

@Composable
fun ThemeAwareSystemBars() {
    val isDark = isSystemInDarkTheme()
    
    AppTheme(isDarkTheme = isDark) {
        SystemBars(
            colors = if (isDark) {
                SystemBarColor(
                    statusBarColor = Color.Black,
                    navigationBarColor = Color.Black
                )
            } else {
                SystemBarColor(
                    statusBarColor = Color.White,
                    navigationBarColor = Color.White
                )
            }
        )
        
        // App content
    }
}

Best Practices

  1. Call Early: Place SystemBars at the top level of your composition
  2. Consistent Colors: Match system bar colors to adjacent UI elements
  3. Dark Mode: Test both light and dark themes
  4. Contrast: Ensure sufficient contrast between content and bars
  5. Transitions: Animate color changes for smooth transitions
  6. Insets: Use systemBarsPadding() to avoid content overlap
  7. Screen Specific: Update colors when navigating between screens

Platform Support

  • Android: Full support (API 21+)
  • iOS: Not applicable (iOS manages status bar differently)
  • Desktop: Not applicable (no system bars)
  • Web: Not applicable (no system bars)

Implementation Details

Under the hood, SystemBars:
  1. Enables edge-to-edge display using Android’s enableEdgeToEdge()
  2. Sets system bars to transparent
  3. Adjusts icon colors based on the luminance of provided colors
  4. Uses SystemBarStyle.dark() for light icons
  5. Uses SystemBarStyle.light() for dark icons

Troubleshooting

Content Hidden Behind Bars

// Add system bars padding
Box(
    modifier = Modifier
        .fillMaxSize()
        .systemBarsPadding() // ✓ Correct
) {
    // Content
}

Wrong Icon Colors

// Ensure color values match your UI
SystemBars(
    colors = SystemBarColor(
        statusBarColor = actualTopBarColor, // Use actual color
        navigationBarColor = actualBottomBarColor
    )
)

Not Working on Device

Ensure you’re using ComponentActivity:
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppTheme {
                SystemBars(/* ... */)
                // Content
            }
        }
    }
}

Source Reference

See the full implementation in SystemBars.kt:16-56 (Android) and SystemBarsDefaultInsets.kt (insets utilities).

Build docs developers (and LLMs) love