Skip to content

Instantly share code, notes, and snippets.

@bmc08gt
Created December 14, 2023 17:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bmc08gt/8a24c2fba166054fe78f6755b7d8026f to your computer and use it in GitHub Desktop.
Save bmc08gt/8a24c2fba166054fe78f6755b7d8026f to your computer and use it in GitHub Desktop.
SettingsSectionScope
interface SettingsSectionScope {
fun item(
icon: ImageVector? = null,
title: String,
subtitle: String? = null,
endSlot: @Composable () -> Unit = { },
onClick: (() -> Unit)? = null,
)
@Composable
fun Icon(imageVector: ImageVector) {
Icon(
modifier = Modifier
.size(24.dp),
painter = rememberVectorPainter(imageVector),
contentDescription = null
)
}
}
private class SettingsSectionScopeImpl : SettingsSectionScope {
val items = mutableListOf<@Composable () -> Unit>()
override fun item(
icon: ImageVector?,
title: String,
subtitle: String?,
endSlot: @Composable () -> Unit,
onClick: (() -> Unit)?,
) {
items += {
SettingsItem(
title = title,
subtitle = subtitle,
icon = icon?.let { { Icon(it) } },
endSlot = endSlot,
onClick = onClick,
)
}
}
}
@Composable
fun SettingsItem(
modifier: Modifier = Modifier,
title: String,
icon: (@Composable () -> Unit)? = null,
subtitle: String? = null,
endSlot: @Composable () -> Unit = { },
onClick: (() -> Unit)? = null,
) {
Row(
modifier = modifier
.addIf(onClick != null) { Modifier.clickable { onClick?.invoke() } }
.padding(
vertical = MaterialTheme.dimens.staticGrid.x4,
horizontal = MaterialTheme.dimens.staticGrid.x3
),
) {
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
icon?.invoke()
Column(
modifier = Modifier
.padding(start = MaterialTheme.dimens.staticGrid.x2)
.weight(1f)
) {
Text(title)
if (subtitle != null) {
Text(
subtitle,
color = LocalContentColor.current.copy(alpha = 0.54f),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
Box(
modifier = Modifier
.padding(
end = if (onClick == null) MaterialTheme.dimens.staticGrid.x2 else 0.dp)
) {
endSlot()
}
if (onClick != null) {
Icon(
modifier = Modifier
.align(Alignment.CenterVertically)
.padding(start = MaterialTheme.dimens.staticGrid.x1),
imageVector = Icons.Rounded.ChevronRight,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
contentDescription = null
)
}
}
}
@Composable
fun SettingsSection(
modifier: Modifier = Modifier,
title: String? = null,
backgroundColor: Color = MaterialTheme.colorScheme.surface,
contentColor: Color = MaterialTheme.colorScheme.onSurface,
content: SettingsSectionScope.() -> Unit,
) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(MaterialTheme.dimens.staticGrid.x2)
) {
if (title != null) {
Text(text = title, style = MaterialTheme.typography.titleMedium)
}
Surface(
modifier = Modifier.fillMaxWidth(),
tonalElevation = 0.dp,
shadowElevation = 2.dp,
color = backgroundColor,
contentColor = contentColor,
shape = MaterialTheme.shapes.large
) {
val scope = remember { SettingsSectionScopeImpl() }
.apply(content)
.items
Column {
scope.forEach { item ->
item()
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment