Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MorphingTitleTopAppBar.kt +40 −33 Original line number Original line Diff line number Diff line Loading @@ -33,7 +33,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.LocalContentColor import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ProvideTextStyle import androidx.compose.material3.Text import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable Loading @@ -48,6 +47,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.layoutId import androidx.compose.ui.layout.layoutId Loading @@ -62,10 +62,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.lerp as lerpDp import androidx.compose.ui.util.lerp import androidx.compose.ui.util.lerp import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsSize import com.android.settingslib.spa.framework.theme.SettingsSpace import com.android.settingslib.spa.framework.theme.SettingsSpace import kotlin.math.roundToInt import kotlin.math.roundToInt Loading Loading @@ -194,11 +191,8 @@ private fun TwoRowsTopAppBar( // Interpolated properties for the single title // Interpolated properties for the single title val interpolatedTextStyle = val interpolatedTextStyle = lerpTextStyle(expandedTextStyle, collapsedTextStyle, collapsedFraction) lerpTextStyle(expandedTextStyle, collapsedTextStyle, collapsedFraction) val expandedTitlePaddingStart = SettingsSpace.small4 // Left padding val navigationIconPaddingStart = SettingsSpace.small3 val collapsedTitlePaddingStart = val expandedTitlePaddingStart = SettingsSpace.small4 expandedTitlePaddingStart + SettingsSize.medium3 + SettingsSpace.small3 // Icon + padding val interpolatedPaddingStart = lerpDp(expandedTitlePaddingStart, collapsedTitlePaddingStart, collapsedFraction) val currentMaxLines = val currentMaxLines = if (collapsedFraction < 0.5f) expandedTitleMaxLines else collapsedTitleMaxLines if (collapsedFraction < 0.5f) expandedTitleMaxLines else collapsedTitleMaxLines Loading @@ -212,7 +206,7 @@ private fun TwoRowsTopAppBar( ) { ) { Layout( Layout( content = { content = { Box(Modifier.layoutId("navigationIcon").padding(start = SettingsSpace.small3)) { Box(Modifier.layoutId("navigationIcon")) { CompositionLocalProvider( CompositionLocalProvider( LocalContentColor provides colors.navigationIconContentColor, LocalContentColor provides colors.navigationIconContentColor, content = navigationIcon, content = navigationIcon, Loading @@ -220,22 +214,13 @@ private fun TwoRowsTopAppBar( } } Box(Modifier.layoutId("title")) { Box(Modifier.layoutId("title")) { ProvideTextStyle(value = interpolatedTextStyle) { Title( CompositionLocalProvider( LocalContentColor provides colors.titleContentColor, localDensityDisableFontScale(), ) { Text( text = titleText, text = titleText, modifier = color = colors.titleContentColor, Modifier.padding(end = SettingsDimension.itemPaddingEnd) .semantics { heading() }, overflow = TextOverflow.Ellipsis, maxLines = currentMaxLines, maxLines = currentMaxLines, textStyle = interpolatedTextStyle, ) ) } } } } Box(Modifier.layoutId("actionIcons").padding(end = TopAppBarHorizontalPadding)) { Box(Modifier.layoutId("actionIcons").padding(end = TopAppBarHorizontalPadding)) { CompositionLocalProvider( CompositionLocalProvider( Loading @@ -255,10 +240,22 @@ private fun TwoRowsTopAppBar( .first { it.layoutId == "actionIcons" } .first { it.layoutId == "actionIcons" } .measure(constraints.copy(minWidth = 0)) .measure(constraints.copy(minWidth = 0)) val titleHorizontalPaddingPx = val collapsedTitlePaddingStartPx = density.run { density.run { interpolatedPaddingStart.toPx() + SettingsDimension.itemPaddingEnd.toPx() val navigationIconWidth = navigationIconPlaceable.width if (navigationIconWidth > 0) { navigationIconWidth + SettingsSpace.small3.toPx() // Icon + padding } else { 0f } } } val interpolatedPaddingStartPx = density.run { expandedTitlePaddingStart.toPx() + collapsedTitlePaddingStartPx * collapsedFraction } val titleHorizontalPaddingPx = density.run { interpolatedPaddingStartPx + SettingsSpace.small1.toPx() } val titleMaxWidth = val titleMaxWidth = (constraints.maxWidth - (constraints.maxWidth - collapsedFraction * actionIconsPlaceable.width - collapsedFraction * actionIconsPlaceable.width - Loading @@ -276,7 +273,7 @@ private fun TwoRowsTopAppBar( layout(layoutWidth, layoutHeight) { layout(layoutWidth, layoutHeight) { navigationIconPlaceable.placeRelative( navigationIconPlaceable.placeRelative( x = 0, x = navigationIconPaddingStart.toPx().roundToInt(), y = ((pinnedHeightPx - navigationIconPlaceable.height) / 2f).roundToInt(), y = ((pinnedHeightPx - navigationIconPlaceable.height) / 2f).roundToInt(), ) ) Loading @@ -296,12 +293,8 @@ private fun TwoRowsTopAppBar( val interpolatedTitleY = lerp(titleYExpanded, titleYCollapsed, collapsedFraction) val interpolatedTitleY = lerp(titleYExpanded, titleYCollapsed, collapsedFraction) // Calculate X position for the title // Similar to TopAppBarLayout: place after nav icon, respecting TopAppBarTitleInset val titleX = density.run { interpolatedPaddingStart.toPx() } titlePlaceable.placeRelative( titlePlaceable.placeRelative( x = titleX.roundToInt(), x = interpolatedPaddingStartPx.roundToInt(), y = interpolatedTitleY.roundToInt(), y = interpolatedTitleY.roundToInt(), ) ) } } Loading @@ -309,6 +302,20 @@ private fun TwoRowsTopAppBar( } } } } @Composable private fun Title(text: String, color: Color, maxLines: Int, textStyle: TextStyle) { CompositionLocalProvider(localDensityDisableFontScale()) { Text( text = text, modifier = Modifier.padding(end = SettingsSpace.small1).semantics { heading() }, color = color, overflow = TextOverflow.Ellipsis, maxLines = maxLines, style = textStyle, ) } } private val MaxHeight = 179.dp private val MaxHeight = 179.dp private val LargeTitleBottomPadding = 28.dp private val LargeTitleBottomPadding = 28.dp private val TopAppBarHorizontalPadding = 4.dp private val TopAppBarHorizontalPadding = 4.dp Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MorphingTitleTopAppBar.kt +40 −33 Original line number Original line Diff line number Diff line Loading @@ -33,7 +33,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.LocalContentColor import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ProvideTextStyle import androidx.compose.material3.Text import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable Loading @@ -48,6 +47,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.layoutId import androidx.compose.ui.layout.layoutId Loading @@ -62,10 +62,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.lerp as lerpDp import androidx.compose.ui.util.lerp import androidx.compose.ui.util.lerp import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsSize import com.android.settingslib.spa.framework.theme.SettingsSpace import com.android.settingslib.spa.framework.theme.SettingsSpace import kotlin.math.roundToInt import kotlin.math.roundToInt Loading Loading @@ -194,11 +191,8 @@ private fun TwoRowsTopAppBar( // Interpolated properties for the single title // Interpolated properties for the single title val interpolatedTextStyle = val interpolatedTextStyle = lerpTextStyle(expandedTextStyle, collapsedTextStyle, collapsedFraction) lerpTextStyle(expandedTextStyle, collapsedTextStyle, collapsedFraction) val expandedTitlePaddingStart = SettingsSpace.small4 // Left padding val navigationIconPaddingStart = SettingsSpace.small3 val collapsedTitlePaddingStart = val expandedTitlePaddingStart = SettingsSpace.small4 expandedTitlePaddingStart + SettingsSize.medium3 + SettingsSpace.small3 // Icon + padding val interpolatedPaddingStart = lerpDp(expandedTitlePaddingStart, collapsedTitlePaddingStart, collapsedFraction) val currentMaxLines = val currentMaxLines = if (collapsedFraction < 0.5f) expandedTitleMaxLines else collapsedTitleMaxLines if (collapsedFraction < 0.5f) expandedTitleMaxLines else collapsedTitleMaxLines Loading @@ -212,7 +206,7 @@ private fun TwoRowsTopAppBar( ) { ) { Layout( Layout( content = { content = { Box(Modifier.layoutId("navigationIcon").padding(start = SettingsSpace.small3)) { Box(Modifier.layoutId("navigationIcon")) { CompositionLocalProvider( CompositionLocalProvider( LocalContentColor provides colors.navigationIconContentColor, LocalContentColor provides colors.navigationIconContentColor, content = navigationIcon, content = navigationIcon, Loading @@ -220,22 +214,13 @@ private fun TwoRowsTopAppBar( } } Box(Modifier.layoutId("title")) { Box(Modifier.layoutId("title")) { ProvideTextStyle(value = interpolatedTextStyle) { Title( CompositionLocalProvider( LocalContentColor provides colors.titleContentColor, localDensityDisableFontScale(), ) { Text( text = titleText, text = titleText, modifier = color = colors.titleContentColor, Modifier.padding(end = SettingsDimension.itemPaddingEnd) .semantics { heading() }, overflow = TextOverflow.Ellipsis, maxLines = currentMaxLines, maxLines = currentMaxLines, textStyle = interpolatedTextStyle, ) ) } } } } Box(Modifier.layoutId("actionIcons").padding(end = TopAppBarHorizontalPadding)) { Box(Modifier.layoutId("actionIcons").padding(end = TopAppBarHorizontalPadding)) { CompositionLocalProvider( CompositionLocalProvider( Loading @@ -255,10 +240,22 @@ private fun TwoRowsTopAppBar( .first { it.layoutId == "actionIcons" } .first { it.layoutId == "actionIcons" } .measure(constraints.copy(minWidth = 0)) .measure(constraints.copy(minWidth = 0)) val titleHorizontalPaddingPx = val collapsedTitlePaddingStartPx = density.run { density.run { interpolatedPaddingStart.toPx() + SettingsDimension.itemPaddingEnd.toPx() val navigationIconWidth = navigationIconPlaceable.width if (navigationIconWidth > 0) { navigationIconWidth + SettingsSpace.small3.toPx() // Icon + padding } else { 0f } } } val interpolatedPaddingStartPx = density.run { expandedTitlePaddingStart.toPx() + collapsedTitlePaddingStartPx * collapsedFraction } val titleHorizontalPaddingPx = density.run { interpolatedPaddingStartPx + SettingsSpace.small1.toPx() } val titleMaxWidth = val titleMaxWidth = (constraints.maxWidth - (constraints.maxWidth - collapsedFraction * actionIconsPlaceable.width - collapsedFraction * actionIconsPlaceable.width - Loading @@ -276,7 +273,7 @@ private fun TwoRowsTopAppBar( layout(layoutWidth, layoutHeight) { layout(layoutWidth, layoutHeight) { navigationIconPlaceable.placeRelative( navigationIconPlaceable.placeRelative( x = 0, x = navigationIconPaddingStart.toPx().roundToInt(), y = ((pinnedHeightPx - navigationIconPlaceable.height) / 2f).roundToInt(), y = ((pinnedHeightPx - navigationIconPlaceable.height) / 2f).roundToInt(), ) ) Loading @@ -296,12 +293,8 @@ private fun TwoRowsTopAppBar( val interpolatedTitleY = lerp(titleYExpanded, titleYCollapsed, collapsedFraction) val interpolatedTitleY = lerp(titleYExpanded, titleYCollapsed, collapsedFraction) // Calculate X position for the title // Similar to TopAppBarLayout: place after nav icon, respecting TopAppBarTitleInset val titleX = density.run { interpolatedPaddingStart.toPx() } titlePlaceable.placeRelative( titlePlaceable.placeRelative( x = titleX.roundToInt(), x = interpolatedPaddingStartPx.roundToInt(), y = interpolatedTitleY.roundToInt(), y = interpolatedTitleY.roundToInt(), ) ) } } Loading @@ -309,6 +302,20 @@ private fun TwoRowsTopAppBar( } } } } @Composable private fun Title(text: String, color: Color, maxLines: Int, textStyle: TextStyle) { CompositionLocalProvider(localDensityDisableFontScale()) { Text( text = text, modifier = Modifier.padding(end = SettingsSpace.small1).semantics { heading() }, color = color, overflow = TextOverflow.Ellipsis, maxLines = maxLines, style = textStyle, ) } } private val MaxHeight = 179.dp private val MaxHeight = 179.dp private val LargeTitleBottomPadding = 28.dp private val LargeTitleBottomPadding = 28.dp private val TopAppBarHorizontalPadding = 4.dp private val TopAppBarHorizontalPadding = 4.dp