Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt +33 −0 Original line number Diff line number Diff line Loading @@ -25,3 +25,36 @@ fun Modifier.contentDescription(contentDescription: String?) = if (contentDescription != null) this.semantics { this.contentDescription = contentDescription } else this /** * Concatenates this modifier with another if `condition` is true. * * This method allows inline conditional addition of modifiers to a modifier chain. Instead of * writing * * ``` * val aModifier = Modifier.a() * val bModifier = if(condition) aModifier.b() else aModifier * Composable(modifier = bModifier) * ``` * * You can instead write * * ``` * Composable(modifier = Modifier.a().thenIf(condition){ * Modifier.b() * } * ``` * * This makes the modifier chain easier to read. * * Note that unlike the non-factory version, the conditional modifier is recreated each time, and * may never be created at all. * * @param condition Whether or not to apply the modifiers. * @param factory Creates the modifier to concatenate with the current one. * @return a Modifier representing this modifier followed by other in sequence. * @see Modifier.then */ inline fun Modifier.thenIf(condition: Boolean, crossinline factory: () -> Modifier): Modifier = if (condition) this.then(factory()) else this packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt +9 −8 Original line number Diff line number Diff line Loading @@ -36,12 +36,13 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.min import com.android.settingslib.spa.framework.compose.thenIf import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsOpacity.alphaForEnabled import com.android.settingslib.spa.framework.theme.SettingsShape import com.android.settingslib.spa.framework.theme.SettingsTheme import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled import com.android.settingslib.spa.widget.ui.LocalIsInCategory import com.android.settingslib.spa.widget.ui.SettingsTitle @Composable Loading @@ -57,18 +58,18 @@ internal fun BaseLayout( paddingVertical: Dp = SettingsDimension.itemPaddingVertical, widget: @Composable () -> Unit = {}, ) { val surfaceBright = MaterialTheme.colorScheme.surfaceBright Row( modifier = modifier .fillMaxWidth() .semantics(mergeDescendants = true) {} .then( if (isSpaExpressiveEnabled) .thenIf(isSpaExpressiveEnabled) { Modifier.heightIn(min = SettingsDimension.preferenceMinHeight) .clip(SettingsShape.CornerExtraSmall) .background(MaterialTheme.colorScheme.surfaceBright) else Modifier ) } .thenIf(isSpaExpressiveEnabled && LocalIsInCategory.current) { Modifier.clip(SettingsShape.CornerExtraSmall).background(surfaceBright) } .padding(end = paddingEnd), verticalAlignment = Alignment.CenterVertically, ) { Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt +12 −9 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ import androidx.compose.material.icons.outlined.TouchApp import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember Loading Loading @@ -99,7 +101,7 @@ fun Category(title: String? = null, content: @Composable ColumnScope.() -> Unit) verticalArrangement = if (isSpaExpressiveEnabled) Arrangement.spacedBy(SettingsDimension.paddingTiny) else Arrangement.Top, content = content, content = { CompositionLocalProvider(LocalIsInCategory provides true) { content() } }, ) } } Loading @@ -109,15 +111,14 @@ fun Category(title: String? = null, content: @Composable ColumnScope.() -> Unit) * * @param list The list of items to display. * @param entry The entry for each list item according to its index in list. * @param key Optional. The key for each item in list to provide unique item identifiers, making * the list more efficient. * @param title Optional. Category title for each item or each group of items in the list. It * should be decided by the index. * @param key Optional. The key for each item in list to provide unique item identifiers, making the * list more efficient. * @param title Optional. Category title for each item or each group of items in the list. It should * be decided by the index. * @param bottomPadding Optional. Bottom outside padding of the category. * @param state Optional. State of LazyList. * @param content Optional. Content to be shown at the top of the category. */ @Composable fun LazyCategory( list: List<Any>, Loading @@ -144,17 +145,19 @@ fun LazyCategory( verticalArrangement = Arrangement.spacedBy(SettingsDimension.paddingTiny), state = state, ) { item { content() } item { CompositionLocalProvider(LocalIsInCategory provides true) { content() } } items(count = list.size, key = key) { title?.invoke(it)?.let { title -> CategoryTitle(title) } val entryPreference = entry(it) entryPreference() CompositionLocalProvider(LocalIsInCategory provides true) { entry(it)() } } } } } /** LocalIsInCategory containing the if the current composable is in a category. */ internal val LocalIsInCategory = compositionLocalOf { false } @Preview @Composable private fun CategoryPreview() { Loading Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt +33 −0 Original line number Diff line number Diff line Loading @@ -25,3 +25,36 @@ fun Modifier.contentDescription(contentDescription: String?) = if (contentDescription != null) this.semantics { this.contentDescription = contentDescription } else this /** * Concatenates this modifier with another if `condition` is true. * * This method allows inline conditional addition of modifiers to a modifier chain. Instead of * writing * * ``` * val aModifier = Modifier.a() * val bModifier = if(condition) aModifier.b() else aModifier * Composable(modifier = bModifier) * ``` * * You can instead write * * ``` * Composable(modifier = Modifier.a().thenIf(condition){ * Modifier.b() * } * ``` * * This makes the modifier chain easier to read. * * Note that unlike the non-factory version, the conditional modifier is recreated each time, and * may never be created at all. * * @param condition Whether or not to apply the modifiers. * @param factory Creates the modifier to concatenate with the current one. * @return a Modifier representing this modifier followed by other in sequence. * @see Modifier.then */ inline fun Modifier.thenIf(condition: Boolean, crossinline factory: () -> Modifier): Modifier = if (condition) this.then(factory()) else this
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt +9 −8 Original line number Diff line number Diff line Loading @@ -36,12 +36,13 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.min import com.android.settingslib.spa.framework.compose.thenIf import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsOpacity.alphaForEnabled import com.android.settingslib.spa.framework.theme.SettingsShape import com.android.settingslib.spa.framework.theme.SettingsTheme import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled import com.android.settingslib.spa.widget.ui.LocalIsInCategory import com.android.settingslib.spa.widget.ui.SettingsTitle @Composable Loading @@ -57,18 +58,18 @@ internal fun BaseLayout( paddingVertical: Dp = SettingsDimension.itemPaddingVertical, widget: @Composable () -> Unit = {}, ) { val surfaceBright = MaterialTheme.colorScheme.surfaceBright Row( modifier = modifier .fillMaxWidth() .semantics(mergeDescendants = true) {} .then( if (isSpaExpressiveEnabled) .thenIf(isSpaExpressiveEnabled) { Modifier.heightIn(min = SettingsDimension.preferenceMinHeight) .clip(SettingsShape.CornerExtraSmall) .background(MaterialTheme.colorScheme.surfaceBright) else Modifier ) } .thenIf(isSpaExpressiveEnabled && LocalIsInCategory.current) { Modifier.clip(SettingsShape.CornerExtraSmall).background(surfaceBright) } .padding(end = paddingEnd), verticalAlignment = Alignment.CenterVertically, ) { Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt +12 −9 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ import androidx.compose.material.icons.outlined.TouchApp import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember Loading Loading @@ -99,7 +101,7 @@ fun Category(title: String? = null, content: @Composable ColumnScope.() -> Unit) verticalArrangement = if (isSpaExpressiveEnabled) Arrangement.spacedBy(SettingsDimension.paddingTiny) else Arrangement.Top, content = content, content = { CompositionLocalProvider(LocalIsInCategory provides true) { content() } }, ) } } Loading @@ -109,15 +111,14 @@ fun Category(title: String? = null, content: @Composable ColumnScope.() -> Unit) * * @param list The list of items to display. * @param entry The entry for each list item according to its index in list. * @param key Optional. The key for each item in list to provide unique item identifiers, making * the list more efficient. * @param title Optional. Category title for each item or each group of items in the list. It * should be decided by the index. * @param key Optional. The key for each item in list to provide unique item identifiers, making the * list more efficient. * @param title Optional. Category title for each item or each group of items in the list. It should * be decided by the index. * @param bottomPadding Optional. Bottom outside padding of the category. * @param state Optional. State of LazyList. * @param content Optional. Content to be shown at the top of the category. */ @Composable fun LazyCategory( list: List<Any>, Loading @@ -144,17 +145,19 @@ fun LazyCategory( verticalArrangement = Arrangement.spacedBy(SettingsDimension.paddingTiny), state = state, ) { item { content() } item { CompositionLocalProvider(LocalIsInCategory provides true) { content() } } items(count = list.size, key = key) { title?.invoke(it)?.let { title -> CategoryTitle(title) } val entryPreference = entry(it) entryPreference() CompositionLocalProvider(LocalIsInCategory provides true) { entry(it)() } } } } } /** LocalIsInCategory containing the if the current composable is in a category. */ internal val LocalIsInCategory = compositionLocalOf { false } @Preview @Composable private fun CategoryPreview() { Loading