Move preference dividers to layout

This commit is contained in:
Suphon Thanakornpakapong
2021-10-09 13:17:11 +07:00
parent a8205e6bd2
commit dae08a5b4c
25 changed files with 176 additions and 76 deletions
@@ -48,7 +48,6 @@ fun AppDrawerPreferences() {
label = stringResource(id = R.string.hidden_apps_label),
subtitle = resources.getQuantityString(R.plurals.apps_count, hiddenAppsCount(), hiddenAppsCount()),
destination = subRoute(name = AppDrawerRoutes.HIDDEN_APPS),
showDivider = false
)
SliderPreference(
label = stringResource(id = R.string.background_opacity),
@@ -62,7 +61,6 @@ fun AppDrawerPreferences() {
SwitchPreference(
adapter = prefs.searchAutoShowKeyboard.getAdapter(),
label = stringResource(id = R.string.pref_search_auto_show_keyboard),
showDivider = false
)
SwitchPreference(
adapter = prefs.useFuzzySearch.getAdapter(),
@@ -76,7 +74,6 @@ fun AppDrawerPreferences() {
adapter = prefs.allAppsColumns.getAdapter(),
step = 1,
valueRange = 3..10,
showDivider = false
)
}
PreferenceGroup(heading = stringResource(id = R.string.icons)) {
@@ -86,7 +83,6 @@ fun AppDrawerPreferences() {
step = 0.1f,
valueRange = 0.5F..1.5F,
showAsPercentage = true,
showDivider = false
)
val allAppsIconLabels = prefs.allAppsIconLabels.getAdapter()
SwitchPreference(
@@ -42,7 +42,6 @@ fun DockPreferences() {
SwitchPreference(
adapter = prefs.enableHotseatQsb.getAdapter(),
label = stringResource(id = R.string.hotseat_qsb_label),
showDivider = false
)
}
PreferenceGroup(heading = stringResource(id = R.string.grid)) {
@@ -51,7 +50,6 @@ fun DockPreferences() {
adapter = prefs.hotseatColumns.getAdapter(),
step = 1,
valueRange = 3..10,
showDivider = false
)
}
}
@@ -43,7 +43,6 @@ fun FolderPreferences() {
adapter = prefs.folderColumns.getAdapter(),
step = 1,
valueRange = 2..5,
showDivider = false
)
SliderPreference(
label = stringResource(id = R.string.max_folder_rows),
@@ -103,12 +103,12 @@ fun FontSelection(fontPref: BasePreferenceManager.FontPref) {
preferenceGroupItems(
filteredItems,
isFirstChild = true,
key = { _, family -> family.toString() }
key = { _, family -> family.toString() },
dividerStartIndent = 40.dp
) { index, family ->
FontSelectionItem(
adapter = adapter,
family = family,
showDivider = index != 0
family = family
)
}
}
@@ -118,8 +118,7 @@ fun FontSelection(fontPref: BasePreferenceManager.FontPref) {
@Composable
private fun FontSelectionItem(
adapter: PreferenceAdapter<FontCache.Font>,
family: FontCache.Family,
showDivider: Boolean
family: FontCache.Family
) {
val selected = family.variants.any { it.value == adapter.state.value }
PreferenceTemplate(
@@ -155,8 +154,6 @@ private fun FontSelectionItem(
}
} else null,
modifier = Modifier.clickable { adapter.onChange(family.default) },
showDivider = showDivider,
dividerIndent = 40.dp,
verticalPadding = 0.dp
)
}
@@ -51,7 +51,6 @@ fun GeneralPreferences() {
adapter = prefs.allowRotation.getAdapter(),
label = stringResource(id = R.string.home_screen_rotation_label),
description = stringResource(id = R.string.home_screen_rotaton_description),
showDivider = false
)
NotificationDotsPreference()
NavigationActionPreference(
@@ -69,20 +68,19 @@ fun GeneralPreferences() {
)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val wrapAdaptiveIcons = prefs.wrapAdaptiveIcons.observeAsState()
val wrapAdaptiveIcons = prefs.wrapAdaptiveIcons.getAdapter()
PreferenceGroup(
heading = stringResource(id = R.string.auto_adaptive_icons_label),
description = stringResource(id = (R.string.adaptive_icon_background_description)),
showDescription = wrapAdaptiveIcons.value
showDescription = wrapAdaptiveIcons.state.value
) {
SwitchPreference(
adapter = prefs.wrapAdaptiveIcons.getAdapter(),
adapter = wrapAdaptiveIcons,
label = stringResource(id = R.string.auto_adaptive_icons_label),
description = stringResource(id = R.string.auto_adaptive_icons_description),
showDivider = false
)
AnimatedVisibility(
visible = wrapAdaptiveIcons.value,
visible = wrapAdaptiveIcons.state.value,
enter = expandVertically() + fadeIn(),
exit = shrinkVertically() + fadeOut()
) {
@@ -90,13 +90,12 @@ fun HiddenAppsPreferences() {
}
preferenceGroupItems(
items = apps,
isFirstChild = true
) { index, app ->
isFirstChild = true,
dividerStartIndent = 40.dp
) { _, app ->
AppItem(
app = app,
onClick = toggleHiddenApp,
showDivider = index != 0,
widgetSize = 24.dp,
) {
Checkbox(
checked = hiddenApps.contains(app.key.toString()),
@@ -112,11 +111,8 @@ fun HiddenAppsPreferences() {
PreferenceLazyColumn(
enabled = false,
) {
preferenceGroupItems(count = 20, isFirstChild = true) { index ->
AppItemPlaceholder(
showDivider = index != 0,
widgetSize = 24.dp,
) {
preferenceGroupItems(count = 20, isFirstChild = true, dividerStartIndent = 40.dp) {
AppItemPlaceholder {
Spacer(Modifier.width(24.dp))
}
}
@@ -44,7 +44,6 @@ fun HomeScreenPreferences() {
SwitchPreference(
prefs.addIconToHome.getAdapter(),
label = stringResource(id = R.string.auto_add_shortcuts_label),
showDivider = false
)
SwitchPreference(
prefs.wallpaperScrolling.getAdapter(),
@@ -62,7 +61,6 @@ fun HomeScreenPreferences() {
label = stringResource(id = R.string.minus_one_enable),
description = if (feedAvailable) null else stringResource(id = R.string.minus_one_unavailable),
enabled = feedAvailable,
showDivider = false
)
SwitchPreference(
prefs.smartSpaceEnable.getAdapter(),
@@ -83,7 +81,6 @@ fun HomeScreenPreferences() {
adapter = prefs.workspaceColumns.getAdapter(),
step = 1,
valueRange = 3..10,
showDivider = false
)
SliderPreference(
label = stringResource(id = R.string.home_screen_rows),
@@ -99,7 +96,6 @@ fun HomeScreenPreferences() {
step = 0.1f,
valueRange = 0.5F..1.5F,
showAsPercentage = true,
showDivider = false
)
val showHomeLabels = prefs.showHomeLabels.getAdapter()
SwitchPreference(
@@ -55,14 +55,13 @@ fun IconPackPreferences() {
PreferenceLayoutLazyColumn(label = stringResource(id = R.string.icon_pack)) {
preferenceGroupItems(
items = iconPacks,
isFirstChild = true
) { index, iconPack ->
isFirstChild = true,
dividerStartIndent = 40.dp
) { _, iconPack ->
AppItem(
label = iconPack.name,
icon = remember(iconPack) { iconPack.icon.toBitmap() },
onClick = { iconPackPackage = iconPack.packageName },
showDivider = index != 0,
widgetSize = 24.dp,
) {
RadioButton(
selected = iconPackPackage == iconPack.packageName,
@@ -28,7 +28,6 @@ fun QuickstepPreferences() {
SwitchPreference(
adapter = prefs.clearAllAsAction.getAdapter(),
label = stringResource(id = R.string.clear_all_as_action_label),
showDivider = false
)
}
val overrideWindowCornerRadius by prefs.overrideWindowCornerRadius.observeAsState()
@@ -40,7 +39,6 @@ fun QuickstepPreferences() {
SwitchPreference(
adapter = prefs.overrideWindowCornerRadius.getAdapter(),
label = stringResource(id = R.string.override_window_corner_radius_label),
showDivider = false
)
AnimatedVisibility(
visible = overrideWindowCornerRadius,
@@ -233,8 +233,7 @@ fun About() {
name = it.name,
description = stringResource(it.descriptionRes),
url = it.socialUrl,
photoUrl = it.photoUrl,
showDivider = index != 0
photoUrl = it.photoUrl
)
}
}
@@ -244,16 +243,14 @@ fun About() {
name = it.name,
description = stringResource(it.descriptionRes),
url = it.socialUrl,
photoUrl = it.photoUrl,
showDivider = index != 0
photoUrl = it.photoUrl
)
}
}
PreferenceGroup {
NavigationActionPreference(
label = stringResource(id = R.string.acknowledgements),
destination = subRoute(name = AboutRoutes.LICENSES),
showDivider = false,
destination = subRoute(name = AboutRoutes.LICENSES)
)
ClickablePreference(
label = stringResource(id = R.string.translate),
@@ -35,7 +35,7 @@ import app.lawnchair.ui.preferences.components.PreferenceTemplate
import coil.compose.rememberImagePainter
@Composable
fun ContributorRow(name: String, description: String, photoUrl: String, url: String, showDivider: Boolean = true) {
fun ContributorRow(name: String, description: String, photoUrl: String, url: String, showDivider: Boolean = false) {
val context = LocalContext.current
PreferenceTemplate(
@@ -57,14 +57,14 @@ fun Licenses() {
LoadingScreen(optionalLicenses) { licenses ->
PreferenceLayoutLazyColumn(label = stringResource(id = R.string.acknowledgements)) {
preferenceGroupItems(licenses, isFirstChild = true) { index, license ->
LicenseItem(license = license, index = index, showDivider = index != 0)
LicenseItem(license = license, index = index)
}
}
}
}
@Composable
fun LicenseItem(license: License, index: Int, showDivider: Boolean) {
fun LicenseItem(license: License, index: Int) {
val navController = LocalNavController.current
val destination = subRoute(name = "$index")
@@ -78,7 +78,6 @@ fun LicenseItem(license: License, index: Int, showDivider: Boolean) {
},
modifier = Modifier
.clickable { navController.navigate(route = destination) },
showDivider = showDivider
)
}
@@ -33,7 +33,7 @@ val presets = presetColors.map {
@Composable
@ExperimentalMaterialApi
@ExperimentalAnimationApi
fun AccentColorPreference(showDivider: Boolean = true) {
fun AccentColorPreference(showDivider: Boolean = false) {
ColorPreference(
previewColor = MaterialTheme.colors.primary.toArgb(),
customColorAdapter = preferenceManager().accentColor.getAdapter(),
@@ -37,7 +37,7 @@ import com.google.accompanist.placeholder.material.placeholder
fun AppItem(
app: App,
onClick: (app: App) -> Unit,
showDivider: Boolean = true,
showDivider: Boolean = false,
widgetSize: Dp = 0.dp,
widget: (@Composable () -> Unit)? = null,
) {
@@ -56,7 +56,7 @@ fun AppItem(
label: String,
icon: Bitmap,
onClick: () -> Unit,
showDivider: Boolean = true,
showDivider: Boolean = false,
widgetSize: Dp = 0.dp,
widget: (@Composable () -> Unit)? = null,
) {
@@ -84,7 +84,7 @@ fun AppItem(
@Composable
fun AppItemPlaceholder(
showDivider: Boolean = true,
showDivider: Boolean = false,
widgetSize: Dp = 0.dp,
widget: (@Composable () -> Unit)? = null,
) {
@@ -118,7 +118,7 @@ fun AppItemPlaceholder(
@Composable
private fun AppItemLayout(
modifier: Modifier = Modifier,
showDivider: Boolean = true,
showDivider: Boolean = false,
widgetSize: Dp = 0.dp,
widget: (@Composable () -> Unit)? = null,
icon: @Composable () -> Unit,
@@ -29,7 +29,7 @@ fun ClickablePreference(
label: String,
subtitle: String? = null,
onClick: () -> Unit,
showDivider: Boolean = true
showDivider: Boolean = false
) {
PreferenceTemplate(
title = { Text(text = label) },
@@ -0,0 +1,90 @@
package app.lawnchair.ui.preferences.components
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import kotlin.math.roundToInt
@Composable
fun DividerColumn(
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.12f),
thickness: Dp = 1.dp,
startIndent: Dp = 0.dp,
endIndent: Dp = 0.dp,
content: @Composable () -> Unit
) {
val state = remember { DividersState() }
val density = LocalDensity.current
val thicknessPx = with(density) { thickness.toPx() }
val startIndentPx = with(density) { (startIndent + 16.dp).toPx() }
val endIndentPx = with(density) { (endIndent + 16.dp).toPx() }
Layout(
modifier = modifier
.drawDividers(state, color, thicknessPx, startIndentPx, endIndentPx),
content = content
) { measurables, constraints ->
// Don't constrain child views further, measure them with given constraints
// List of measured children
val placeables = measurables.map { measurable ->
// Measure each children
measurable.measure(constraints)
}
val width = constraints.maxWidth
val dividersHeight = thicknessPx.roundToInt() * (placeables.size - 1)
val height = placeables.sumOf { it.height } + dividersHeight
layout(width, height) {
val dividerPositions = mutableListOf<Int>()
// Track the y co-ord we have placed children up to
var yPosition = 0
// Place children in the parent layout
placeables.forEachIndexed { index, placeable ->
if (index > 0) {
dividerPositions.add(yPosition)
yPosition += thicknessPx.roundToInt()
}
// Position item on the screen
placeable.placeRelative(x = 0, y = yPosition)
// Record the y co-ord placed up to
yPosition += placeable.height
}
state.dividerPositions = dividerPositions
}
}
}
private fun Modifier.drawDividers(
state: DividersState,
color: Color,
thickness: Float,
startIndentPx: Float,
endIndentPx: Float
): Modifier {
return drawBehind {
state.dividerPositions.forEach { yPos ->
drawRect(
color = color,
topLeft = Offset(startIndentPx, yPos.toFloat()),
size = Size(size.width - startIndentPx - endIndentPx, thickness)
)
}
}
}
private class DividersState {
var dividerPositions by mutableStateOf(emptyList<Int>())
}
@@ -13,7 +13,7 @@ import app.lawnchair.ui.preferences.LocalNavController
fun FontPreference(
adapter: PreferenceAdapter<FontCache.Font>,
label: String,
showDivider: Boolean = true
showDivider: Boolean = false
) {
val navController = LocalNavController.current
@@ -21,12 +21,15 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import app.lawnchair.util.smartBorder
@@ -35,11 +38,22 @@ fun LazyListScope.preferenceGroupItems(
heading: String? = null,
isFirstChild: Boolean,
key: ((index: Int) -> Any)? = null,
showDividers: Boolean = true,
dividerStartIndent: Dp = 0.dp,
dividerEndIndent: Dp = 0.dp,
itemContent: @Composable LazyItemScope.(index: Int) -> Unit
) {
val actualStartIndent = 16.dp + dividerStartIndent
val actualEndIndent = 16.dp + dividerEndIndent
item { PreferenceGroupHeading(heading, isFirstChild) }
items(count, key) {
PreferenceGroupItem(cutTop = it > 0, cutBottom = it < count - 1) {
if (showDividers && it > 0) {
Divider(
modifier = Modifier
.padding(start = actualStartIndent, end = actualEndIndent)
)
}
itemContent(it)
}
}
@@ -50,20 +64,30 @@ inline fun <T> LazyListScope.preferenceGroupItems(
heading: String? = null,
isFirstChild: Boolean,
noinline key: ((index: Int, item: T) -> Any)? = null,
showDividers: Boolean = true,
dividerStartIndent: Dp = 0.dp,
dividerEndIndent: Dp = 0.dp,
crossinline itemContent: @Composable LazyItemScope.(index: Int, item: T) -> Unit
) {
preferenceGroupItems(
items.size,
heading,
isFirstChild,
if (key != null) { index: Int -> key(index, items[index]) } else null
if (key != null) { index: Int -> key(index, items[index]) } else null,
showDividers = showDividers,
dividerStartIndent = dividerStartIndent,
dividerEndIndent = dividerEndIndent,
) {
itemContent(it, items[it])
}
}
@Composable
fun PreferenceGroupItem(cutTop: Boolean, cutBottom: Boolean, content: @Composable () -> Unit) {
fun PreferenceGroupItem(
cutTop: Boolean,
cutBottom: Boolean,
content: @Composable () -> Unit
) {
val shape = remember(cutTop, cutBottom) {
val top = if (cutTop) 0.dp else 12.dp
val bottom = if (cutBottom) 0.dp else 12.dp
@@ -26,7 +26,7 @@ fun <T> ListPreference(
entries: List<ListPreferenceEntry<T>>,
label: String,
enabled: Boolean = true,
showDivider: Boolean = true
showDivider: Boolean = false
) {
val sheetState = rememberBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
val scope = rememberCoroutineScope()
@@ -27,7 +27,7 @@ fun NavigationActionPreference(
label: String,
subtitle: String? = null,
destination: String,
showDivider: Boolean = true
showDivider: Boolean = false
) {
val navController = LocalNavController.current
@@ -23,6 +23,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import app.lawnchair.util.smartBorder
@@ -33,20 +35,31 @@ fun PreferenceGroup(
isFirstChild: Boolean = false,
description: String? = null,
showDescription: Boolean = true,
showDividers: Boolean = true,
dividerStartIndent: Dp = 0.dp,
dividerEndIndent: Dp = 0.dp,
content: @Composable () -> Unit
) {
PreferenceGroupHeading(heading, isFirstChild)
Column(
modifier = Modifier
.padding(horizontal = 16.dp)
.smartBorder(
1.dp,
color = MaterialTheme.colors.onBackground.copy(alpha = 0.12F),
shape = MaterialTheme.shapes.large
)
.clip(shape = MaterialTheme.shapes.large)
) {
content()
val columnModifier = Modifier
.padding(horizontal = 16.dp)
.smartBorder(
1.dp,
color = MaterialTheme.colors.onBackground.copy(alpha = 0.12F),
shape = MaterialTheme.shapes.large
)
.clip(shape = MaterialTheme.shapes.large)
if (showDividers) {
DividerColumn(
modifier = columnModifier,
startIndent = dividerStartIndent,
endIndent = dividerEndIndent,
content = content
)
} else {
Column(modifier = columnModifier) {
content()
}
}
PreferenceGroupDescription(description, showDescription)
}
@@ -35,7 +35,7 @@ fun PreferenceTemplate(
startWidget: (@Composable () -> Unit)? = null,
endWidget: (@Composable () -> Unit)? = null,
enabled: Boolean = true,
showDivider: Boolean = true,
showDivider: Boolean = false,
dividerIndent: Dp = 0.dp,
applyPaddings: Boolean = true,
horizontalPadding: Dp = 16.dp,
@@ -33,7 +33,7 @@ fun SliderPreference(
valueRange: ClosedRange<Int>,
step: Int,
showAsPercentage: Boolean = false,
showDivider: Boolean = true
showDivider: Boolean = false
) {
val transformedAdapter = rememberTransformAdapter(
adapter = adapter,
@@ -59,7 +59,7 @@ fun SliderPreference(
valueRange: ClosedFloatingPointRange<Float>,
step: Float,
showAsPercentage: Boolean = false,
showDivider: Boolean = true
showDivider: Boolean = false
) {
var adapterValue by adapter
var sliderValue by remember { mutableStateOf(adapterValue) }
@@ -32,7 +32,7 @@ fun SwitchPreference(
label: String,
description: String? = null,
enabled: Boolean = true,
showDivider: Boolean = true
showDivider: Boolean = false
) {
// TODO: Wrap overflowing text instead of using an ellipsis.
PreferenceTemplate(
@@ -24,7 +24,7 @@ val themeEntries = listOf(
@ExperimentalMaterialApi
@Composable
fun ThemePreference(showDivider: Boolean = true) {
fun ThemePreference(showDivider: Boolean = false) {
ListPreference(
adapter = preferenceManager().launcherTheme.getAdapter(),
entries = themeEntries,