Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b393602 authored by Yuchen's avatar Yuchen
Browse files

[expressive design] Update topAppBar layout.

Also Fix shape of back button.

Test: visual
Bug: 360916599
Flag: EXEMPT bug fix
Change-Id: Icc8981a2929ef2adab219ea9dca1c5a6a341dfa7
parent 10b67750
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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)
+27 −9
Original line number Diff line number Diff line
@@ -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. */
@@ -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,
        )
    }
}
+44 −36
Original line number Diff line number Diff line
@@ -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
@@ -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,
@@ -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() },
@@ -194,7 +202,7 @@ private class TopAppBarColors(
        return lerp(
            containerColor,
            scrolledContainerColor,
            FastOutLinearInEasing.transform(colorTransitionFraction)
            FastOutLinearInEasing.transform(colorTransitionFraction),
        )
    }

@@ -241,7 +249,7 @@ private fun SingleRowTopAppBar(
            Row(
                horizontalArrangement = Arrangement.End,
                verticalAlignment = Alignment.CenterVertically,
                content = actions
                content = actions,
            )
        }

@@ -296,7 +304,7 @@ private fun TwoRowsTopAppBar(
    windowInsets: WindowInsets,
    colors: TopAppBarColors,
    pinnedHeight: Dp,
    scrollBehavior: TopAppBarScrollBehavior?
    scrollBehavior: TopAppBarScrollBehavior?,
) {
    if (MaxHeightWithoutTitle <= pinnedHeight) {
        throw IllegalArgumentException(
@@ -333,7 +341,7 @@ private fun TwoRowsTopAppBar(
            Row(
                horizontalArrangement = Arrangement.End,
                verticalAlignment = Alignment.CenterVertically,
                content = actions
                content = actions,
            )
        }
    val topTitleAlpha = { TopTitleAlphaEasing.transform(colorTransitionFraction()) }
@@ -356,9 +364,9 @@ private fun TwoRowsTopAppBar(
                        scrollBehavior.state,
                        velocity,
                        scrollBehavior.flingAnimationSpec,
                        scrollBehavior.snapAnimationSpec
                        scrollBehavior.snapAnimationSpec,
                    )
                }
                },
            )
        } else {
            Modifier
@@ -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.
@@ -430,7 +439,7 @@ private fun TwoRowsTopAppBar(
                titleBottomPadding = titleBottomPaddingPx,
                hideTitleSemantics = hideBottomRowSemantics,
                navigationIcon = {},
                actions = {}
                actions = {},
            )
        }
    }
@@ -485,7 +494,7 @@ private fun TopAppBarLayout(
            Box(Modifier.layoutId("navigationIcon").padding(start = TopAppBarHorizontalPadding)) {
                CompositionLocalProvider(
                    LocalContentColor provides navigationIconContentColor,
                    content = navigationIcon
                    content = navigationIcon,
                )
            }
            Box(
@@ -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
@@ -552,7 +561,7 @@ private fun TopAppBarLayout(
            // Navigation icon
            navigationIconPlaceable.placeRelative(
                x = 0,
                y = (layoutHeight - navigationIconPlaceable.height) / 2
                y = (layoutHeight - navigationIconPlaceable.height) / 2,
            )

            // Title
@@ -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,
            )
        }
    }
@@ -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.
@@ -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
@@ -633,7 +640,7 @@ private suspend fun settleAppBar(
                } else {
                    state.heightOffsetLimit
                },
                animationSpec = snapAnimationSpec
                animationSpec = snapAnimationSpec,
            ) {
                state.heightOffset = value
            }
@@ -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