DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Settings Screen in Compose — Switch, Slider & Selection Dialogs

Settings Screen in Compose — Switch, Slider & Selection Dialogs

Create professional settings screens in Jetpack Compose with Switch, Slider, dialogs, and persistent DataStore integration.

SwitchSetting Component

Build reusable switch items with ListItem:

@Composable
fun SwitchSetting(
    title: String,
    description: String? = null,
    isChecked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier
) {
    ListItem(
        modifier = modifier.clickable { onCheckedChange(!isChecked) },
        headlineContent = { Text(title) },
        supportingContent = description?.let { { Text(it) } },
        trailingContent = {
            Switch(
                checked = isChecked,
                onCheckedChange = onCheckedChange
            )
        }
    )
}

@Composable
fun SettingsScreenWithSwitches() {
    var darkMode by remember { mutableStateOf(false) }
    var notifications by remember { mutableStateOf(true) }

    LazyColumn {
        item {
            SwitchSetting(
                title = "Dark Mode",
                description = "Enable dark theme",
                isChecked = darkMode,
                onCheckedChange = { darkMode = it }
            )
        }
        item {
            SwitchSetting(
                title = "Notifications",
                description = "Receive push notifications",
                isChecked = notifications,
                onCheckedChange = { notifications = it }
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

SliderSetting with Value Label

Display numeric settings with visual feedback:

@Composable
fun SliderSetting(
    title: String,
    value: Float,
    onValueChange: (Float) -> Unit,
    valueRange: ClosedFloatingPointRange<Float> = 0f..100f,
    modifier: Modifier = Modifier
) {
    Column(modifier = modifier.padding(16.dp)) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(title, style = MaterialTheme.typography.titleMedium)
            Text(
                value.toInt().toString(),
                style = MaterialTheme.typography.labelLarge,
                color = MaterialTheme.colorScheme.primary
            )
        }

        Slider(
            value = value,
            onValueChange = onValueChange,
            valueRange = valueRange,
            modifier = Modifier.fillMaxWidth()
        )
    }
}

@Composable
fun VolumeSliderExample() {
    var volume by remember { mutableFloatStateOf(70f) }

    SliderSetting(
        title = "Volume",
        value = volume,
        onValueChange = { volume = it }
    )
}
Enter fullscreen mode Exit fullscreen mode

ClickableSetting for Navigation

Clickable list items for navigation to detail screens:

@Composable
fun ClickableSetting(
    title: String,
    description: String? = null,
    icon: (@Composable () -> Unit)? = null,
    onClick: () -> Unit,
    modifier: Modifier = Modifier
) {
    ListItem(
        modifier = modifier.clickable(onClick = onClick),
        headlineContent = { Text(title) },
        supportingContent = description?.let { { Text(it) } },
        leadingContent = icon,
        trailingContent = {
            Icon(Icons.AutoMirrored.Filled.ChevronRight, contentDescription = null)
        }
    )
}

@Composable
fun SettingsNavigation() {
    ClickableSetting(
        title = "Account",
        description = "Manage your account settings",
        icon = { Icon(Icons.Filled.AccountCircle, contentDescription = null) },
        onClick = { /* Navigate to account */ }
    )
}
Enter fullscreen mode Exit fullscreen mode

Section Headers

Group settings with colored section headers:

@Composable
fun SettingsSection(
    title: String,
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Column(modifier = modifier) {
        Text(
            title,
            modifier = Modifier
                .fillMaxWidth()
                .background(MaterialTheme.colorScheme.primaryContainer)
                .padding(16.dp),
            color = MaterialTheme.colorScheme.onPrimaryContainer,
            style = MaterialTheme.typography.labelLarge
        )
        content()
    }
}

@Composable
fun CategorizedSettings() {
    LazyColumn {
        item {
            SettingsSection(title = "Display") {
                SwitchSetting(
                    title = "Dark Mode",
                    isChecked = true,
                    onCheckedChange = {}
                )
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Language Selection Dialog with RadioButton

Implement choice dialogs for preference selection:

@Composable
fun LanguageDialog(
    isOpen: Boolean,
    currentLanguage: String,
    onDismiss: () -> Unit,
    onLanguageSelected: (String) -> Unit
) {
    val languages = listOf("English", "Spanish", "French", "Japanese")

    if (isOpen) {
        AlertDialog(
            onDismissRequest = onDismiss,
            title = { Text("Select Language") },
            text = {
                LazyColumn {
                    items(languages) { language ->
                        Row(
                            modifier = Modifier
                                .fillMaxWidth()
                                .clickable { onLanguageSelected(language) }
                                .padding(8.dp),
                            verticalAlignment = Alignment.CenterVertically
                        ) {
                            RadioButton(
                                selected = language == currentLanguage,
                                onClick = { onLanguageSelected(language) }
                            )
                            Text(language, modifier = Modifier.padding(start = 8.dp))
                        }
                    }
                }
            },
            confirmButton = {
                TextButton(onClick = onDismiss) {
                    Text("Done")
                }
            }
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

DataStore Integration for Persistence

Persist settings across app restarts:

// Create DataStore
val Context.settingsDataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

object SettingsKeys {
    val DARK_MODE = booleanPreferencesKey("dark_mode")
    val VOLUME = floatPreferencesKey("volume")
    val LANGUAGE = stringPreferencesKey("language")
}

@Composable
fun PersistentSettingsScreen(context: Context) {
    val settingsDataStore = context.settingsDataStore
    val darkMode = settingsDataStore.data
        .map { it[SettingsKeys.DARK_MODE] ?: false }
        .collectAsState(initial = false)

    val coroutineScope = rememberCoroutineScope()

    SwitchSetting(
        title = "Dark Mode",
        isChecked = darkMode.value,
        onCheckedChange = { newValue ->
            coroutineScope.launch {
                settingsDataStore.edit { preferences ->
                    preferences[SettingsKeys.DARK_MODE] = newValue
                }
            }
        }
    )
}
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  • ListItem with Switch for boolean toggles
  • Slider for numeric range settings with visual feedback
  • Clickable ListItems for navigation to detail screens
  • Section headers to organize related settings
  • RadioButton dialogs for single-selection preferences
  • DataStore to persist user settings across sessions

Combine these patterns to build complete, user-friendly settings experiences!


8 Android app templates: Gumroad

Top comments (0)