Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTypography.kt +3 −0 Original line number Diff line number Diff line Loading @@ -162,3 +162,6 @@ internal fun rememberSettingsTypography(): Typography { /** Creates a new [TextStyle] which font weight set to medium. */ internal fun TextStyle.toMediumWeight() = copy(fontWeight = FontWeight.Medium, letterSpacing = 0.01.em) internal fun TextStyle.toSemiBoldWeight() = copy(fontWeight = FontWeight.SemiBold, letterSpacing = 0.01.em) packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt +27 −9 Original line number Diff line number Diff line Loading @@ -41,9 +41,7 @@ import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled internal fun NavigateBack() { val navController = LocalNavController.current val contentDescription = stringResource(R.string.abc_action_bar_up_description) BackAction(contentDescription) { navController.navigateBack() } BackAction(contentDescription) { navController.navigateBack() } } /** Action that collapses the search bar. */ Loading @@ -55,15 +53,35 @@ internal fun CollapseAction(onClick: () -> Unit) { @Composable private fun BackAction(contentDescription: String, onClick: () -> Unit) { IconButton(onClick) { IconButton( onClick = onClick, modifier = if (isSpaExpressiveEnabled) Modifier .padding( start = SettingsDimension.paddingLarge, end = SettingsDimension.paddingSmall, top = SettingsDimension.paddingExtraSmall, bottom = SettingsDimension.paddingExtraSmall, ) .size(SettingsDimension.actionIconWidth, SettingsDimension.actionIconHeight) .clip(SettingsShape.CornerExtraLarge) else Modifier, ) { Icon( imageVector = Icons.AutoMirrored.Outlined.ArrowBack, contentDescription = contentDescription, modifier = if (isSpaExpressiveEnabled) Modifier .size(SettingsDimension.actionIconWidth, SettingsDimension.actionIconHeight) modifier = if (isSpaExpressiveEnabled) Modifier .size( SettingsDimension.actionIconWidth, SettingsDimension.actionIconHeight, ) .clip(SettingsShape.CornerExtraLarge) .background(MaterialTheme.colorScheme.surfaceContainerHigh) .padding(SettingsDimension.actionIconPadding) else Modifier .background(MaterialTheme.colorScheme.surfaceContainerHighest) .padding(SettingsDimension.actionIconPadding) else Modifier, ) } } Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt +44 −36 Original line number Diff line number Diff line Loading @@ -78,7 +78,9 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled import com.android.settingslib.spa.framework.theme.settingsBackground import com.android.settingslib.spa.framework.theme.toSemiBoldWeight import kotlin.math.abs import kotlin.math.max import kotlin.math.roundToInt Loading Loading @@ -116,8 +118,12 @@ internal fun CustomizedLargeTopAppBar( ) { TwoRowsTopAppBar( title = { Title(title = title, maxLines = 3) }, titleTextStyle = MaterialTheme.typography.displaySmall, smallTitleTextStyle = MaterialTheme.typography.titleMedium, titleTextStyle = if (isSpaExpressiveEnabled) MaterialTheme.typography.displaySmall.toSemiBoldWeight() else MaterialTheme.typography.displaySmall, smallTitleTextStyle = if (isSpaExpressiveEnabled) MaterialTheme.typography.titleLarge.toSemiBoldWeight() else MaterialTheme.typography.titleLarge, titleBottomPadding = LargeTitleBottomPadding, smallTitle = { Title(title = title, maxLines = 1) }, modifier = modifier, Loading @@ -136,7 +142,9 @@ private fun Title(title: String, maxLines: Int = Int.MAX_VALUE) { text = title, modifier = Modifier.padding( start = SettingsDimension.itemPaddingAround, start = if (isSpaExpressiveEnabled) SettingsDimension.paddingExtraSmall else SettingsDimension.itemPaddingAround, end = SettingsDimension.itemPaddingEnd, ) .semantics { heading() }, Loading Loading @@ -194,7 +202,7 @@ private class TopAppBarColors( return lerp( containerColor, scrolledContainerColor, FastOutLinearInEasing.transform(colorTransitionFraction) FastOutLinearInEasing.transform(colorTransitionFraction), ) } Loading Loading @@ -241,7 +249,7 @@ private fun SingleRowTopAppBar( Row( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, content = actions content = actions, ) } Loading Loading @@ -296,7 +304,7 @@ private fun TwoRowsTopAppBar( windowInsets: WindowInsets, colors: TopAppBarColors, pinnedHeight: Dp, scrollBehavior: TopAppBarScrollBehavior? scrollBehavior: TopAppBarScrollBehavior?, ) { if (MaxHeightWithoutTitle <= pinnedHeight) { throw IllegalArgumentException( Loading Loading @@ -333,7 +341,7 @@ private fun TwoRowsTopAppBar( Row( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, content = actions content = actions, ) } val topTitleAlpha = { TopTitleAlphaEasing.transform(colorTransitionFraction()) } Loading @@ -356,9 +364,9 @@ private fun TwoRowsTopAppBar( scrollBehavior.state, velocity, scrollBehavior.flingAnimationSpec, scrollBehavior.snapAnimationSpec scrollBehavior.snapAnimationSpec, ) } }, ) } else { Modifier Loading Loading @@ -412,7 +420,8 @@ private fun TwoRowsTopAppBar( val measuredMaxHeightPx = density.run { MaxHeightWithoutTitle.toPx() + coordinates.size.height.toFloat() coordinates.size.height.toFloat() + titleBaselineHeight.toPx() } // Allow larger max height for multi-line title, but do not reduce // max height to prevent flaky. Loading @@ -430,7 +439,7 @@ private fun TwoRowsTopAppBar( titleBottomPadding = titleBottomPaddingPx, hideTitleSemantics = hideBottomRowSemantics, navigationIcon = {}, actions = {} actions = {}, ) } } Loading Loading @@ -485,7 +494,7 @@ private fun TopAppBarLayout( Box(Modifier.layoutId("navigationIcon").padding(start = TopAppBarHorizontalPadding)) { CompositionLocalProvider( LocalContentColor provides navigationIconContentColor, content = navigationIcon content = navigationIcon, ) } Box( Loading @@ -504,18 +513,18 @@ private fun TopAppBarLayout( fontScale = if (titleScaleDisabled) 1f else fontScale, ) }, content = title content = title, ) } } Box(Modifier.layoutId("actionIcons").padding(end = TopAppBarHorizontalPadding)) { CompositionLocalProvider( LocalContentColor provides actionIconContentColor, content = actions content = actions, ) } }, modifier = modifier modifier = modifier, ) { measurables, constraints -> val navigationIconPlaceable = measurables Loading Loading @@ -552,7 +561,7 @@ private fun TopAppBarLayout( // Navigation icon navigationIconPlaceable.placeRelative( x = 0, y = (layoutHeight - navigationIconPlaceable.height) / 2 y = (layoutHeight - navigationIconPlaceable.height) / 2, ) // Title Loading @@ -570,17 +579,17 @@ private fun TopAppBarLayout( titlePlaceable.height - max( 0, titleBottomPadding - titlePlaceable.height + titleBaseline titleBottomPadding - titlePlaceable.height + titleBaseline, ) // Arrangement.Top else -> 0 } }, ) // Action icons actionIconsPlaceable.placeRelative( x = constraints.maxWidth - actionIconsPlaceable.width, y = (layoutHeight - actionIconsPlaceable.height) / 2 y = (layoutHeight - actionIconsPlaceable.height) / 2, ) } } Loading @@ -595,7 +604,7 @@ private suspend fun settleAppBar( state: TopAppBarState, velocity: Float, flingAnimationSpec: DecayAnimationSpec<Float>?, snapAnimationSpec: AnimationSpec<Float>? snapAnimationSpec: AnimationSpec<Float>?, ): Velocity { // Check if the app bar is completely collapsed/expanded. If so, no need to settle the app bar, // and just return Zero Velocity. Loading @@ -609,11 +618,9 @@ private suspend fun settleAppBar( // continue the motion to expand or collapse the app bar. if (flingAnimationSpec != null && abs(velocity) > 1f) { var lastValue = 0f AnimationState( initialValue = 0f, initialVelocity = velocity, ) .animateDecay(flingAnimationSpec) { AnimationState(initialValue = 0f, initialVelocity = velocity).animateDecay( flingAnimationSpec ) { val delta = value - lastValue val initialHeightOffset = state.heightOffset state.heightOffset = initialHeightOffset + delta Loading @@ -633,7 +640,7 @@ private suspend fun settleAppBar( } else { state.heightOffsetLimit }, animationSpec = snapAnimationSpec animationSpec = snapAnimationSpec, ) { state.heightOffset = value } Loading @@ -647,9 +654,10 @@ private suspend fun settleAppBar( // Medium or Large app bar. private val TopTitleAlphaEasing = CubicBezierEasing(.8f, 0f, .8f, .15f) internal val MaxHeightWithoutTitle = 124.dp internal val MaxHeightWithoutTitle = if (isSpaExpressiveEnabled) 84.dp else 124.dp internal val DefaultTitleHeight = 52.dp internal val ContainerHeight = 56.dp private val titleBaselineHeight = if (isSpaExpressiveEnabled) 8.dp else 0.dp private val LargeTitleBottomPadding = 28.dp private val TopAppBarHorizontalPadding = 4.dp Loading Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTypography.kt +3 −0 Original line number Diff line number Diff line Loading @@ -162,3 +162,6 @@ internal fun rememberSettingsTypography(): Typography { /** Creates a new [TextStyle] which font weight set to medium. */ internal fun TextStyle.toMediumWeight() = copy(fontWeight = FontWeight.Medium, letterSpacing = 0.01.em) internal fun TextStyle.toSemiBoldWeight() = copy(fontWeight = FontWeight.SemiBold, letterSpacing = 0.01.em)
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt +27 −9 Original line number Diff line number Diff line Loading @@ -41,9 +41,7 @@ import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled internal fun NavigateBack() { val navController = LocalNavController.current val contentDescription = stringResource(R.string.abc_action_bar_up_description) BackAction(contentDescription) { navController.navigateBack() } BackAction(contentDescription) { navController.navigateBack() } } /** Action that collapses the search bar. */ Loading @@ -55,15 +53,35 @@ internal fun CollapseAction(onClick: () -> Unit) { @Composable private fun BackAction(contentDescription: String, onClick: () -> Unit) { IconButton(onClick) { IconButton( onClick = onClick, modifier = if (isSpaExpressiveEnabled) Modifier .padding( start = SettingsDimension.paddingLarge, end = SettingsDimension.paddingSmall, top = SettingsDimension.paddingExtraSmall, bottom = SettingsDimension.paddingExtraSmall, ) .size(SettingsDimension.actionIconWidth, SettingsDimension.actionIconHeight) .clip(SettingsShape.CornerExtraLarge) else Modifier, ) { Icon( imageVector = Icons.AutoMirrored.Outlined.ArrowBack, contentDescription = contentDescription, modifier = if (isSpaExpressiveEnabled) Modifier .size(SettingsDimension.actionIconWidth, SettingsDimension.actionIconHeight) modifier = if (isSpaExpressiveEnabled) Modifier .size( SettingsDimension.actionIconWidth, SettingsDimension.actionIconHeight, ) .clip(SettingsShape.CornerExtraLarge) .background(MaterialTheme.colorScheme.surfaceContainerHigh) .padding(SettingsDimension.actionIconPadding) else Modifier .background(MaterialTheme.colorScheme.surfaceContainerHighest) .padding(SettingsDimension.actionIconPadding) else Modifier, ) } } Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt +44 −36 Original line number Diff line number Diff line Loading @@ -78,7 +78,9 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled import com.android.settingslib.spa.framework.theme.settingsBackground import com.android.settingslib.spa.framework.theme.toSemiBoldWeight import kotlin.math.abs import kotlin.math.max import kotlin.math.roundToInt Loading Loading @@ -116,8 +118,12 @@ internal fun CustomizedLargeTopAppBar( ) { TwoRowsTopAppBar( title = { Title(title = title, maxLines = 3) }, titleTextStyle = MaterialTheme.typography.displaySmall, smallTitleTextStyle = MaterialTheme.typography.titleMedium, titleTextStyle = if (isSpaExpressiveEnabled) MaterialTheme.typography.displaySmall.toSemiBoldWeight() else MaterialTheme.typography.displaySmall, smallTitleTextStyle = if (isSpaExpressiveEnabled) MaterialTheme.typography.titleLarge.toSemiBoldWeight() else MaterialTheme.typography.titleLarge, titleBottomPadding = LargeTitleBottomPadding, smallTitle = { Title(title = title, maxLines = 1) }, modifier = modifier, Loading @@ -136,7 +142,9 @@ private fun Title(title: String, maxLines: Int = Int.MAX_VALUE) { text = title, modifier = Modifier.padding( start = SettingsDimension.itemPaddingAround, start = if (isSpaExpressiveEnabled) SettingsDimension.paddingExtraSmall else SettingsDimension.itemPaddingAround, end = SettingsDimension.itemPaddingEnd, ) .semantics { heading() }, Loading Loading @@ -194,7 +202,7 @@ private class TopAppBarColors( return lerp( containerColor, scrolledContainerColor, FastOutLinearInEasing.transform(colorTransitionFraction) FastOutLinearInEasing.transform(colorTransitionFraction), ) } Loading Loading @@ -241,7 +249,7 @@ private fun SingleRowTopAppBar( Row( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, content = actions content = actions, ) } Loading Loading @@ -296,7 +304,7 @@ private fun TwoRowsTopAppBar( windowInsets: WindowInsets, colors: TopAppBarColors, pinnedHeight: Dp, scrollBehavior: TopAppBarScrollBehavior? scrollBehavior: TopAppBarScrollBehavior?, ) { if (MaxHeightWithoutTitle <= pinnedHeight) { throw IllegalArgumentException( Loading Loading @@ -333,7 +341,7 @@ private fun TwoRowsTopAppBar( Row( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, content = actions content = actions, ) } val topTitleAlpha = { TopTitleAlphaEasing.transform(colorTransitionFraction()) } Loading @@ -356,9 +364,9 @@ private fun TwoRowsTopAppBar( scrollBehavior.state, velocity, scrollBehavior.flingAnimationSpec, scrollBehavior.snapAnimationSpec scrollBehavior.snapAnimationSpec, ) } }, ) } else { Modifier Loading Loading @@ -412,7 +420,8 @@ private fun TwoRowsTopAppBar( val measuredMaxHeightPx = density.run { MaxHeightWithoutTitle.toPx() + coordinates.size.height.toFloat() coordinates.size.height.toFloat() + titleBaselineHeight.toPx() } // Allow larger max height for multi-line title, but do not reduce // max height to prevent flaky. Loading @@ -430,7 +439,7 @@ private fun TwoRowsTopAppBar( titleBottomPadding = titleBottomPaddingPx, hideTitleSemantics = hideBottomRowSemantics, navigationIcon = {}, actions = {} actions = {}, ) } } Loading Loading @@ -485,7 +494,7 @@ private fun TopAppBarLayout( Box(Modifier.layoutId("navigationIcon").padding(start = TopAppBarHorizontalPadding)) { CompositionLocalProvider( LocalContentColor provides navigationIconContentColor, content = navigationIcon content = navigationIcon, ) } Box( Loading @@ -504,18 +513,18 @@ private fun TopAppBarLayout( fontScale = if (titleScaleDisabled) 1f else fontScale, ) }, content = title content = title, ) } } Box(Modifier.layoutId("actionIcons").padding(end = TopAppBarHorizontalPadding)) { CompositionLocalProvider( LocalContentColor provides actionIconContentColor, content = actions content = actions, ) } }, modifier = modifier modifier = modifier, ) { measurables, constraints -> val navigationIconPlaceable = measurables Loading Loading @@ -552,7 +561,7 @@ private fun TopAppBarLayout( // Navigation icon navigationIconPlaceable.placeRelative( x = 0, y = (layoutHeight - navigationIconPlaceable.height) / 2 y = (layoutHeight - navigationIconPlaceable.height) / 2, ) // Title Loading @@ -570,17 +579,17 @@ private fun TopAppBarLayout( titlePlaceable.height - max( 0, titleBottomPadding - titlePlaceable.height + titleBaseline titleBottomPadding - titlePlaceable.height + titleBaseline, ) // Arrangement.Top else -> 0 } }, ) // Action icons actionIconsPlaceable.placeRelative( x = constraints.maxWidth - actionIconsPlaceable.width, y = (layoutHeight - actionIconsPlaceable.height) / 2 y = (layoutHeight - actionIconsPlaceable.height) / 2, ) } } Loading @@ -595,7 +604,7 @@ private suspend fun settleAppBar( state: TopAppBarState, velocity: Float, flingAnimationSpec: DecayAnimationSpec<Float>?, snapAnimationSpec: AnimationSpec<Float>? snapAnimationSpec: AnimationSpec<Float>?, ): Velocity { // Check if the app bar is completely collapsed/expanded. If so, no need to settle the app bar, // and just return Zero Velocity. Loading @@ -609,11 +618,9 @@ private suspend fun settleAppBar( // continue the motion to expand or collapse the app bar. if (flingAnimationSpec != null && abs(velocity) > 1f) { var lastValue = 0f AnimationState( initialValue = 0f, initialVelocity = velocity, ) .animateDecay(flingAnimationSpec) { AnimationState(initialValue = 0f, initialVelocity = velocity).animateDecay( flingAnimationSpec ) { val delta = value - lastValue val initialHeightOffset = state.heightOffset state.heightOffset = initialHeightOffset + delta Loading @@ -633,7 +640,7 @@ private suspend fun settleAppBar( } else { state.heightOffsetLimit }, animationSpec = snapAnimationSpec animationSpec = snapAnimationSpec, ) { state.heightOffset = value } Loading @@ -647,9 +654,10 @@ private suspend fun settleAppBar( // Medium or Large app bar. private val TopTitleAlphaEasing = CubicBezierEasing(.8f, 0f, .8f, .15f) internal val MaxHeightWithoutTitle = 124.dp internal val MaxHeightWithoutTitle = if (isSpaExpressiveEnabled) 84.dp else 124.dp internal val DefaultTitleHeight = 52.dp internal val ContainerHeight = 56.dp private val titleBaselineHeight = if (isSpaExpressiveEnabled) 8.dp else 0.dp private val LargeTitleBottomPadding = 28.dp private val TopAppBarHorizontalPadding = 4.dp Loading