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

Commit 7870a98d authored by Chaohui Wang's avatar Chaohui Wang
Browse files

[Spa] Polish CustomizedAppBar

- The padding logic better to be part of CustomizedAppBar, instead of
  BackAction
- Paddings polished
- Remove toSemiBoldWeight(), set FontWeight.SemiBold directly to
  Emphasized styles, which can also apply to languages as Chinese
- Fix an issue that when return from other page, the CustomizedAppBar
  collapse again

Bug: 419002002
Flag: EXEMPT bug fix
Test: visual
Change-Id: I7d029be278972ad797fb598c82550bd814579ed8
parent 4d02bcee
Loading
Loading
Loading
Loading
+10 −13
Original line number Diff line number Diff line
@@ -184,7 +184,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            displayLargeEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.displayLargeEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 57.sp,
                    lineHeight = 64.sp,
                    letterSpacing = (-0.2).sp,
@@ -202,7 +202,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            displayMediumEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.displayMediumEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 45.sp,
                    lineHeight = 52.sp,
                    letterSpacing = 0.0.sp,
@@ -220,7 +220,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            displaySmallEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.displaySmallEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 36.sp,
                    lineHeight = 44.sp,
                    letterSpacing = 0.0.sp,
@@ -238,7 +238,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            headlineLargeEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.headlineLargeEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 32.sp,
                    lineHeight = 40.sp,
                    letterSpacing = 0.0.sp,
@@ -256,7 +256,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            headlineMediumEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.headlineMediumEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 28.sp,
                    lineHeight = 36.sp,
                    letterSpacing = 0.0.sp,
@@ -274,7 +274,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            headlineSmallEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.headlineSmallEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 24.sp,
                    lineHeight = 32.sp,
                    letterSpacing = 0.0.sp,
@@ -292,7 +292,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            titleLargeEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.titleLargeEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 22.sp,
                    lineHeight = 28.sp,
                    letterSpacing = 0.02.em,
@@ -346,7 +346,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            bodyLargeEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.bodyLargeEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 16.sp,
                    lineHeight = 24.sp,
                    letterSpacing = 0.01.em,
@@ -364,7 +364,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            bodyMediumEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.bodyMediumEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 14.sp,
                    lineHeight = 20.sp,
                    letterSpacing = 0.01.em,
@@ -382,7 +382,7 @@ private class SettingsTypography(settingsFontFamily: SettingsFontFamily) {
            bodySmallEmphasized =
                TextStyle(
                    fontFamily = settingsFontFamily.bodySmallEmphasized,
                    fontWeight = FontWeight.Medium,
                    fontWeight = FontWeight.SemiBold,
                    fontSize = 12.sp,
                    lineHeight = 16.sp,
                    letterSpacing = 0.01.em,
@@ -457,6 +457,3 @@ 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)
+3 −2
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.WarningAmber
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -57,7 +58,6 @@ import com.android.settingslib.spa.framework.theme.SettingsShape.CornerExtraLarg
import com.android.settingslib.spa.framework.theme.SettingsShape.CornerExtraSmall2
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
import com.android.settingslib.spa.framework.theme.toSemiBoldWeight
import com.android.settingslib.spa.widget.ui.SettingsBody
import com.android.settingslib.spa.widget.ui.SettingsTitle

@@ -157,11 +157,12 @@ fun BannerHeader(imageVector: ImageVector?, iconColor: Color, onDismiss: (() ->
    }
}

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun BannerTitleHeader(title: String, onDismiss: (() -> Unit)? = null) {
    Row(Modifier.fillMaxWidth()) {
        Box(modifier = Modifier.weight(1f)) {
            Text(text = title, style = MaterialTheme.typography.titleMedium.toSemiBoldWeight())
            Text(text = title, style = MaterialTheme.typography.titleMediumEmphasized)
        }
        Spacer(modifier = Modifier.padding(SettingsDimension.paddingSmall))
        DismissButton(onDismiss)
+2 −2
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.framework.theme.SettingsShape
import com.android.settingslib.spa.framework.theme.SettingsSpace
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.framework.theme.toSemiBoldWeight

data class SuggestionCardModel(
    val title: String,
@@ -115,11 +114,12 @@ private fun SuggestionCardIcon(imageVector: ImageVector) {
    }
}

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
private fun SuggestionCardTitle(title: String) {
    Text(
        text = title,
        style = MaterialTheme.typography.titleMedium.toSemiBoldWeight(),
        style = MaterialTheme.typography.titleMediumEmphasized,
        modifier = Modifier.padding(vertical = SettingsDimension.paddingTiny),
        color = MaterialTheme.colorScheme.onSecondaryContainer,
    )
+31 −33
Original line number Diff line number Diff line
@@ -17,24 +17,21 @@
package com.android.settingslib.spa.widget.scaffold

import androidx.appcompat.R
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.outlined.Clear
import androidx.compose.material.icons.outlined.FindInPage
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.android.settingslib.spa.framework.compose.LocalNavController
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.framework.theme.SettingsShape
import com.android.settingslib.spa.framework.theme.SettingsSpace
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled

/** Action that navigates back to last page. */
@@ -52,35 +49,30 @@ internal fun CollapseAction(onClick: () -> Unit) {
    BackAction(contentDescription, onClick)
}

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
private fun BackAction(contentDescription: String, onClick: () -> Unit) {
    IconButton(
        onClick = onClick,
        modifier =
            if (isSpaExpressiveEnabled)
                Modifier.padding(
                    start = SettingsSpace.extraSmall5,
                    end = SettingsDimension.paddingSmall,
                    top = SettingsSpace.extraSmall2,
                    bottom = SettingsSpace.extraSmall2,
    if (isSpaExpressiveEnabled) {
        FilledTonalIconButton(
            onClick = onClick, shape = IconButtonDefaults.smallRoundShape,
            colors = IconButtonDefaults.filledTonalIconButtonColors(
                containerColor = MaterialTheme.colorScheme.surfaceContainerHighest,
            )
                    .size(SettingsDimension.actionIconSize)
                    .clip(SettingsShape.CornerExtraLarge1)
            else Modifier,
        ) {
            ArrowBack(contentDescription)
        }
    } else {
        IconButton(onClick = onClick) { ArrowBack(contentDescription) }
    }
}

@Composable
private fun ArrowBack(contentDescription: String) {
    Icon(
        imageVector = Icons.AutoMirrored.Outlined.ArrowBack,
        contentDescription = contentDescription,
            modifier =
                if (isSpaExpressiveEnabled)
                    Modifier.size(SettingsDimension.actionIconSize)
                        .clip(SettingsShape.CornerExtraLarge1)
                        .background(MaterialTheme.colorScheme.surfaceContainerHighest)
                        .padding(SettingsDimension.actionIconPadding)
                else Modifier,
    )
}
}

/** Action that expends the search bar. */
@Composable
@@ -103,3 +95,9 @@ internal fun ClearAction(onClick: () -> Unit) {
        )
    }
}

@Preview
@Composable
private fun BackActionPreview() {
    SettingsTheme { BackAction("") {} }
}
+47 −35
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProvideTextStyle
@@ -52,7 +53,10 @@ import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
@@ -82,7 +86,6 @@ import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.framework.theme.SettingsSpace
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
@@ -109,7 +112,7 @@ internal fun CustomizedTopAppBar(
}

/** The customized LargeTopAppBar for Settings. */
@OptIn(ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable
internal fun CustomizedLargeTopAppBar(
    title: String,
@@ -119,15 +122,30 @@ internal fun CustomizedLargeTopAppBar(
    scrollBehavior: TopAppBarScrollBehavior? = null,
) {
    TwoRowsTopAppBar(
        title = { Title(title = title, maxLines = 3) },
        title = {
            Title(
                title = title,
                maxLines = 3,
                paddingStart =
                    if (isSpaExpressiveEnabled) 0.dp else SettingsDimension.itemPaddingAround,
            )
        },
        titleTextStyle =
            if (isSpaExpressiveEnabled) MaterialTheme.typography.displaySmall.toSemiBoldWeight()
            if (isSpaExpressiveEnabled) MaterialTheme.typography.displaySmallEmphasized
            else MaterialTheme.typography.displaySmall,
        smallTitleTextStyle =
            if (isSpaExpressiveEnabled) MaterialTheme.typography.titleLarge.toSemiBoldWeight()
            if (isSpaExpressiveEnabled) MaterialTheme.typography.titleLargeEmphasized
            else MaterialTheme.typography.titleLarge,
        titleBottomPadding = LargeTitleBottomPadding,
        smallTitle = { Title(title = title, maxLines = 1) },
        smallTitle = {
            Title(
                title = title,
                maxLines = 1,
                paddingStart =
                    if (isSpaExpressiveEnabled) SettingsSpace.extraSmall6
                    else SettingsDimension.itemPaddingAround,
            )
        },
        modifier = modifier,
        navigationIcon = navigationIcon,
        actions = actions,
@@ -139,17 +157,11 @@ internal fun CustomizedLargeTopAppBar(
}

@Composable
private fun Title(title: String, maxLines: Int = Int.MAX_VALUE) {
private fun Title(title: String, maxLines: Int = Int.MAX_VALUE, paddingStart: Dp) {
    Text(
        text = title,
        modifier =
            Modifier
                .padding(
                    start =
                        if (isSpaExpressiveEnabled) SettingsSpace.extraSmall2
                        else SettingsDimension.itemPaddingAround,
                    end = SettingsDimension.itemPaddingEnd,
                )
            Modifier.padding(start = paddingStart, end = SettingsDimension.itemPaddingEnd)
                .semantics { heading() },
        overflow = TextOverflow.Ellipsis,
        maxLines = maxLines,
@@ -158,7 +170,7 @@ private fun Title(title: String, maxLines: Int = Int.MAX_VALUE) {

@Composable
private fun topAppBarColors() =
    if (isSpaExpressiveEnabled)
    if (isSpaExpressiveEnabled) {
        TopAppBarColors(
            containerColor = MaterialTheme.colorScheme.surfaceContainer,
            scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer,
@@ -166,7 +178,7 @@ private fun topAppBarColors() =
            titleContentColor = MaterialTheme.colorScheme.onSurface,
            actionIconContentColor = MaterialTheme.colorScheme.primary,
        )
    else
    } else {
        TopAppBarColors(
            containerColor = MaterialTheme.colorScheme.settingsBackground,
            scrolledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
@@ -174,6 +186,7 @@ private fun topAppBarColors() =
            titleContentColor = MaterialTheme.colorScheme.onSurface,
            actionIconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
        )
    }

/**
 * Represents the colors used by a top app bar in different states.
@@ -268,16 +281,14 @@ private fun SingleRowTopAppBar(
    // Compose a Surface with a TopAppBarLayout content.
    Box(
        modifier =
            Modifier
                .drawBehind { drawRect(color = colors.scrolledContainerColor) }
            Modifier.drawBehind { drawRect(color = colors.scrolledContainerColor) }
                .semantics { isTraversalGroup = true }
                .pointerInput(Unit) {}
    ) {
        val height = LocalDensity.current.run { ContainerHeight.toPx() }
        TopAppBarLayout(
            modifier =
                Modifier
                    .windowInsetsPadding(windowInsets)
                Modifier.windowInsetsPadding(windowInsets)
                    // clip after padding so we don't show the title over the inset area
                    .clipToBounds(),
            heightPx = height,
@@ -339,9 +350,16 @@ private fun TwoRowsTopAppBar(

    // Sets the app bar's height offset limit to hide just the bottom title area and keep top title
    // visible when collapsed.
    scrollBehavior?.state?.heightOffsetLimit = pinnedHeightPx - maxHeightPx.floatValue
    val heightOffsetLimit = pinnedHeightPx - maxHeightPx.floatValue
    scrollBehavior?.state?.heightOffsetLimit = heightOffsetLimit
    if (isSpaExpressiveEnabled) {
        LaunchedEffect(scrollBehavior?.state?.heightOffsetLimit) { scrollBehavior?.collapse() }
        var hasCollapsedInitially by rememberSaveable(heightOffsetLimit) { mutableStateOf(false) }
        LaunchedEffect(heightOffsetLimit) {
            if (!hasCollapsedInitially) {
                scrollBehavior?.collapse()
                hasCollapsedInitially = true
            }
        }
    }

    // Obtain the container Color from the TopAppBarColors using the `collapsedFraction`, as the
@@ -400,8 +418,7 @@ private fun TwoRowsTopAppBar(
        Column {
            TopAppBarLayout(
                modifier =
                    Modifier
                        .windowInsetsPadding(windowInsets)
                    Modifier.windowInsetsPadding(windowInsets)
                        // clip after padding so we don't show the title over the inset area
                        .clipToBounds(),
                heightPx = pinnedHeightPx,
@@ -438,8 +455,7 @@ private fun TwoRowsTopAppBar(
                                val measuredMaxHeightPx =
                                    density.run {
                                        MaxHeightWithoutTitle.toPx() +
                                            coordinates.size.height.toFloat() +
                                            titleBaselineHeight.toPx()
                                            coordinates.size.height.toFloat()
                                    }
                                // Allow larger max height for multi-line title, but do not reduce
                                // max height to prevent flaky.
@@ -509,17 +525,16 @@ private fun TopAppBarLayout(
) {
    Layout(
        {
            Box(Modifier
                .layoutId("navigationIcon")
                .padding(start = TopAppBarHorizontalPadding)) {
            val iconPaddingStart =
                if (isSpaExpressiveEnabled) SettingsSpace.small3 else TopAppBarHorizontalPadding
            Box(Modifier.layoutId("navigationIcon").padding(start = iconPaddingStart)) {
                CompositionLocalProvider(
                    LocalContentColor provides navigationIconContentColor,
                    content = navigationIcon,
                )
            }
            Box(
                Modifier
                    .layoutId("title")
                Modifier.layoutId("title")
                    .padding(horizontal = TopAppBarHorizontalPadding)
                    .then(if (hideTitleSemantics) Modifier.clearAndSetSemantics {} else Modifier)
                    .graphicsLayer { alpha = titleAlpha() }
@@ -538,9 +553,7 @@ private fun TopAppBarLayout(
                    )
                }
            }
            Box(Modifier
                .layoutId("actionIcons")
                .padding(end = TopAppBarHorizontalPadding)) {
            Box(Modifier.layoutId("actionIcons").padding(end = TopAppBarHorizontalPadding)) {
                CompositionLocalProvider(
                    LocalContentColor provides actionIconContentColor,
                    content = actions,
@@ -680,7 +693,6 @@ private val TopTitleAlphaEasing = CubicBezierEasing(.8f, 0f, .8f, .15f)
internal val MaxHeightWithoutTitle = 124.dp
internal val DefaultTitleHeight = 52.dp
internal val ContainerHeight = 56.dp
private val titleBaselineHeight = 0.dp
private val LargeTitleBottomPadding = 28.dp
private val TopAppBarHorizontalPadding = 4.dp