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

Commit 73e5c22a authored by Lucas Dupin's avatar Lucas Dupin Committed by Android (Google) Code Review
Browse files

Merge "Swipe down should hide ActionList" into main

parents 3459bbe4 f7080ccd
Loading
Loading
Loading
Loading
+81 −33
Original line number Diff line number Diff line
@@ -16,66 +16,114 @@

package com.android.systemui.ambientcue.ui.compose

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.gestures.AnchoredDraggableState
import androidx.compose.foundation.gestures.DraggableAnchors
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.anchoredDraggable
import androidx.compose.foundation.gestures.animateTo
import androidx.compose.foundation.gestures.snapping.SnapPosition.End
import androidx.compose.foundation.gestures.snapping.SnapPosition.Start
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.unit.dp
import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel
import kotlin.math.abs
import kotlin.math.max

@Composable
fun ActionList(
    actions: List<ActionViewModel>,
    visible: Boolean,
    onDismiss: () -> Unit,
    modifier: Modifier = Modifier,
    horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
) {
    val density = LocalDensity.current
    var containerHeightPx by remember { mutableIntStateOf(0) }

    // User should be able to drag down vertically to dismiss the action list.
    // The list will shrink as the user drags.
    val anchoredDraggableState = remember {
        AnchoredDraggableState(initialValue = if (visible) End else Start)
    }
    // A ratio from 0..1 representing the expansion of the list
    val progress by remember {
        derivedStateOf { abs(anchoredDraggableState.offset) / max(1, containerHeightPx) }
    }
    LaunchedEffect(progress) {
        if (progress == 0f) {
            onDismiss()
        }
    }

    LaunchedEffect(visible) { anchoredDraggableState.animateTo(if (visible) End else Start) }

    Column(
        modifier = modifier,
        verticalArrangement = Arrangement.spacedBy(8.dp),
        modifier =
            modifier
                .anchoredDraggable(
                    state = anchoredDraggableState,
                    orientation = Orientation.Vertical,
                    enabled = visible,
                )
                .onGloballyPositioned { layoutCoordinates ->
                    containerHeightPx = layoutCoordinates.size.height
                    anchoredDraggableState.updateAnchors(
                        DraggableAnchors {
                            Start at 0f // Hidden
                            End at -containerHeightPx.toFloat() // Visible
                        }
                    )
                }
                .defaultMinSize(minHeight = 200.dp)
                .fillMaxWidth(),
        verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.Bottom),
        horizontalAlignment = horizontalAlignment,
    ) {
        actions.forEachIndexed { index, action ->
            AnimatedVisibility(
                visible = visible,
                enter =
                    slideInVertically(
                        spring(
                            dampingRatio = Spring.DampingRatioMediumBouncy,
                            stiffness = Spring.StiffnessLow,
                        )
                    ) {
                        with(density) { it * (actions.size - index) }
                    } +
                        scaleIn(
            val scale by
                animateFloatAsState(
                    progress,
                    animationSpec =
                        spring(
                            dampingRatio = Spring.DampingRatioNoBouncy,
                            stiffness = Spring.StiffnessLow,
                            )
                        ),
                exit =
                    slideOutVertically(
                )
            val translation by
                animateFloatAsState(
                    progress,
                    animationSpec =
                        spring(
                            dampingRatio = Spring.DampingRatioMediumBouncy,
                            stiffness = Spring.StiffnessLow,
                        ),
                )

            Chip(
                action = action,
                modifier =
                    Modifier.graphicsLayer {
                        translationY = (1f - translation) * size.height * (actions.size - index)
                        scaleX = scale
                        scaleY = scale
                    },
            )
                    ) {
                        with(density) { it * (actions.size - index) }
                    } + scaleOut(tween(250)),
            ) {
                Chip(action)
            }
        }
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -176,6 +176,7 @@ private fun TaskBarAnd3ButtonAmbientCue(
    ActionList(
        actions = actions,
        visible = visible && expanded,
        onDismiss = { viewModel.collapse() },
        horizontalAlignment = Alignment.End,
        modifier =
            modifier.graphicsLayer {
@@ -214,6 +215,7 @@ private fun NavBarAmbientCue(
    ActionList(
        actions = actions,
        visible = visible && expanded,
        onDismiss = { viewModel.collapse() },
        modifier =
            modifier.padding(
                bottom = NAV_BAR_ACTIONS_PADDING.dp,