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

Commit 68a37df2 authored by Olivier St-Onge's avatar Olivier St-Onge
Browse files

Add marquee to QS tiles.

Text will scroll once, and a blur covers the end of the labels similar to the current QS implementation

Test: manually setting really long tile labels to test marquee
Flag: com.android.systemui.qs_ui_refactor_compose_fragment
Fixes: 395857383

Change-Id: I4dc327449edba115cfa6ea79024dbe02dc1620b5
parent 4496b6f9
Loading
Loading
Loading
Loading
+61 −8
Original line number Diff line number Diff line
@@ -26,12 +26,14 @@ import androidx.compose.animation.graphics.res.animatedVectorResource
import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
import androidx.compose.animation.graphics.vector.AnimatedImageVector
import androidx.compose.foundation.Image
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -50,8 +52,16 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ColorProducer
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
@@ -61,7 +71,7 @@ import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.semantics.toggleableState
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.android.compose.modifiers.size
@@ -74,6 +84,9 @@ import com.android.systemui.common.ui.compose.load
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.SideIconHeight
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.SideIconWidth
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.TILE_INITIAL_DELAY_MILLIS
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.TILE_MARQUEE_ITERATIONS
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.TileLabelBlurWidth
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.longPressLabel
import com.android.systemui.qs.panels.ui.viewmodel.AccessibilityUiState
import com.android.systemui.qs.ui.compose.borderOnFocus
@@ -169,18 +182,15 @@ fun LargeTileLabels(
    val animatedSecondaryLabelColor by
        animateColorAsState(colors.secondaryLabel, label = "QSTileSecondaryLabelColor")
    Column(verticalArrangement = Arrangement.Center, modifier = modifier.fillMaxHeight()) {
        BasicText(
            label,
        TileLabel(
            text = label,
            style = MaterialTheme.typography.labelLarge,
            color = { animatedLabelColor },
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
        )
        if (!TextUtils.isEmpty(secondaryLabel)) {
            BasicText(
            TileLabel(
                secondaryLabel ?: "",
                color = { animatedSecondaryLabelColor },
                maxLines = 1,
                style = MaterialTheme.typography.bodyMedium,
                modifier =
                    Modifier.thenIf(
@@ -261,6 +271,45 @@ fun SmallTileContent(
    }
}

@Composable
private fun TileLabel(
    text: String,
    color: ColorProducer,
    style: TextStyle,
    modifier: Modifier = Modifier,
) {
    BasicText(
        text = text,
        color = color,
        style = style,
        maxLines = 1,
        modifier =
            modifier
                .fillMaxWidth()
                .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen }
                .drawWithContent {
                    drawContent()
                    // Draw a blur over the end of the text
                    val edgeWidthPx = TileLabelBlurWidth.toPx()
                    drawRect(
                        topLeft = Offset(size.width - edgeWidthPx, 0f),
                        size = Size(edgeWidthPx, size.height),
                        brush =
                            Brush.horizontalGradient(
                                colors = listOf(Color.Transparent, Color.Black),
                                startX = size.width,
                                endX = size.width - edgeWidthPx,
                            ),
                        blendMode = BlendMode.DstIn,
                    )
                }
                .basicMarquee(
                    iterations = TILE_MARQUEE_ITERATIONS,
                    initialDelayMillis = TILE_INITIAL_DELAY_MILLIS,
                ),
    )
}

object CommonTileDefaults {
    val IconSize = 32.dp
    val LargeTileIconSize = 28.dp
@@ -268,9 +317,13 @@ object CommonTileDefaults {
    val SideIconHeight = 20.dp
    val ToggleTargetSize = 56.dp
    val TileHeight = 72.dp
    val TilePadding = 8.dp
    val TileStartPadding = 8.dp
    val TileEndPadding = 16.dp
    val TileArrangementPadding = 6.dp
    val InactiveCornerRadius = 50.dp
    val TileLabelBlurWidth = 32.dp
    const val TILE_MARQUEE_ITERATIONS = 1
    const val TILE_INITIAL_DELAY_MILLIS = 2000

    @Composable fun longPressLabel() = stringResource(id = R.string.accessibility_long_click_tile)
}
+3 −3
Original line number Diff line number Diff line
@@ -713,7 +713,7 @@ private fun AvailableTileGridCell(
    // Displays the tile as an icon tile with the label underneath
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = spacedBy(CommonTileDefaults.TilePadding, Alignment.Top),
        verticalArrangement = spacedBy(CommonTileDefaults.TileStartPadding, Alignment.Top),
        modifier =
            modifier
                .graphicsLayer { this.alpha = alpha }
@@ -813,7 +813,7 @@ fun EditTile(
                        placeable.place(startPadding.roundToInt(), 0)
                    }
                }
                .tilePadding(),
                .largeTilePadding(),
    ) {
        // Icon
        Box(Modifier.size(ToggleTargetSize)) {
@@ -847,7 +847,7 @@ private fun toAvailableTiles(

private fun MeasureScope.iconHorizontalCenter(containerSize: Int): Float {
    return (containerSize - ToggleTargetSize.roundToPx()) / 2f -
        CommonTileDefaults.TilePadding.toPx()
        CommonTileDefaults.TileStartPadding.toPx()
}

private fun Modifier.tileBackground(color: Color): Modifier {
+6 −4
Original line number Diff line number Diff line
@@ -84,7 +84,9 @@ import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.qs.flags.QsDetailedView
import com.android.systemui.qs.panels.ui.compose.BounceableInfo
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.InactiveCornerRadius
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.TileEndPadding
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.TileHeight
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.TileStartPadding
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.longPressLabel
import com.android.systemui.qs.panels.ui.viewmodel.DetailsViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileUiState
@@ -270,7 +272,7 @@ fun TileContainer(
                    iconOnly = iconOnly,
                )
                .sysuiResTag(if (iconOnly) TEST_TAG_SMALL else TEST_TAG_LARGE)
                .tilePadding(),
                .thenIf(!iconOnly) { Modifier.largeTilePadding() }, // Icon tiles are center aligned
        content = content,
    )
}
@@ -284,7 +286,7 @@ fun LargeStaticTile(uiState: TileUiState, modifier: Modifier = Modifier) {
            .clip(TileDefaults.animateTileShapeAsState(state = uiState.state).value)
            .background(colors.background)
            .height(TileHeight)
            .tilePadding()
            .largeTilePadding()
    ) {
        LargeTileContent(
            label = uiState.label,
@@ -311,8 +313,8 @@ fun tileHorizontalArrangement(): Arrangement.Horizontal {
    return spacedBy(space = CommonTileDefaults.TileArrangementPadding, alignment = Alignment.Start)
}

fun Modifier.tilePadding(): Modifier {
    return padding(CommonTileDefaults.TilePadding)
fun Modifier.largeTilePadding(): Modifier {
    return padding(start = TileStartPadding, end = TileEndPadding)
}

@Composable