Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/ActionList.kt +102 −14 Original line number Diff line number Diff line Loading @@ -99,8 +99,9 @@ fun ActionList( padding: PaddingValues = PaddingValues(0.dp), horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, portrait: Boolean = true, pillCenter: Offset = Offset.Unspecified, pillCenter: Offset = Offset.Zero, pillWidth: Float = 0f, pillHeight: Float = 0f, rotation: Int = 0, taskBarMode: Boolean = false, ) { Loading @@ -111,6 +112,7 @@ fun ActionList( val minGradientHeight = 70.dp val scrimVerticalPadding = 32.dp val scrimHorizontalPadding = 42.dp val landscapeMode = !portrait && !taskBarMode val smartScrimAlpha by animateFloatAsState( if (expanded) { Loading @@ -127,9 +129,11 @@ fun ActionList( val translateStiffnessMultiplier = 50 val overscrollStiffness = 2063f var containerHeightPx by remember { mutableIntStateOf(0) } var containerWidthPx by remember { mutableIntStateOf(0) } var radius by remember { mutableFloatStateOf(0f) } var wasEverExpanded by remember { mutableStateOf(false) } var actionListCenterPositionX by remember { mutableFloatStateOf(0f) } var actionListCenterPositionY by remember { mutableFloatStateOf(0f) } LaunchedEffect(expanded) { if (expanded) { Loading Loading @@ -225,6 +229,54 @@ fun ActionList( label = "scrimOffsetY", ) val landscapeScrimOffsetX by animateFloatAsState( targetValue = if (!expanded) containerWidthPx.toFloat() + pillWidth else containerWidthPx / 2f, animationSpec = if (expanded || wasEverExpanded) { // Enable animation only when user expands/collapses the action list. tween( durationMillis = 250, // Usually, 200 ms delay is used. But the collapsed delay is reduced to be // 100 ms to ensure the Action chips and background glow disappear at the // same pace. delayMillis = if (expanded) 200 else 100, ) } else { // Disable animation during Compose initialization. snap() }, label = "landscapeScrimOffsetX", ) var landscapeCollapsedScrimOffsetY by remember { mutableFloatStateOf(0f) } val landscapeScrimOffsetY by animateFloatAsState( targetValue = if (!expanded) landscapeCollapsedScrimOffsetY else containerHeightPx / 2f, animationSpec = if (expanded || wasEverExpanded) { // Enable animation only when user expands/collapses the action list. tween(250, delayMillis = 200) } else { // Disable animation during Compose initialization. snap() }, label = "landscapeScrimOffsetY", ) val landscapeScaleX by animateFloatAsState( targetValue = if (!expanded) 0.15f else 1f, animationSpec = tween( durationMillis = 250, // Usually, 200 ms delay is used. But the collapsed delay is reduced to be 100 // ms to ensure the Action chips and background glow disappear at the same pace. delayMillis = if (expanded) 200 else 100, ), label = "landscapeScaleX", ) LaunchedEffect(visible, expanded) { anchoredDraggableState.animateTo(if (visible && expanded) End else Start) } Loading Loading @@ -296,8 +348,11 @@ fun ActionList( ) .onGloballyPositioned { layoutCoordinates -> containerHeightPx = layoutCoordinates.size.height containerWidthPx = layoutCoordinates.size.width actionListCenterPositionX = layoutCoordinates.positionInWindow().x + layoutCoordinates.size.width / 2 actionListCenterPositionY = layoutCoordinates.positionInWindow().y + layoutCoordinates.size.height / 2 anchoredDraggableState.updateAnchors( DraggableAnchors { Start at 0f // Hidden Loading @@ -317,36 +372,69 @@ fun ActionList( val minScaleY = minGradientHeightPx / (radius * 2f) val scaleY = max(minScaleY, size.height / (radius * 2f) * scrimProgress) scale(scaleX = 1f, scaleY = scaleY, pivot = Offset(0f, size.height)) { val leftGradientCenter = scale( scaleX = if (!landscapeMode) 1f else landscapeScaleX, scaleY = scaleY, pivot = Offset(0f, if (!landscapeMode) size.height else 0f), ) { landscapeCollapsedScrimOffsetY = size.height / 2 + pillCenter.y - actionListCenterPositionY val safeScaleY = if (scaleY == 0f || scaleY.isNaN()) 1f else scaleY val safeScaleX = if (landscapeScaleX == 0f || landscapeScaleX.isNaN()) 1f else landscapeScaleX val leftOrUpGradientCenter = if (!landscapeMode) { Offset(size.width / 2 - sidePaddingPx, scrimOffsetY) val rightGradientCenter = } else { Offset( if (rotation == ROTATION_90) { landscapeScrimOffsetX / safeScaleX } else { (containerWidthPx - landscapeScrimOffsetX) / safeScaleX }, (landscapeScrimOffsetY - pillHeight / 2) / safeScaleY, ) } val rightOrDownGradientCenter = if (!landscapeMode) { Offset(size.width / 2 + sidePaddingPx, scrimOffsetY) val leftBrush = } else { Offset( if (rotation == ROTATION_90) { landscapeScrimOffsetX / safeScaleX } else { (containerWidthPx - landscapeScrimOffsetX) / safeScaleX }, (landscapeScrimOffsetY + pillHeight / 2) / safeScaleY, ) } val leftOrUpBrush = Brush.radialGradient( colors = listOf(leftGradientColor, leftGradientColor.copy(alpha = 0f)), center = leftGradientCenter, center = leftOrUpGradientCenter, radius = radius, ) val rightBrush = val rightOrDownBrush = Brush.radialGradient( colors = listOf(rightGradientColor, rightGradientColor.copy(alpha = 0f)), center = rightGradientCenter, center = rightOrDownGradientCenter, radius = radius * 0.85f, ) drawCircle( brush = leftBrush, brush = leftOrUpBrush, alpha = smartScrimAlpha + smartScrimAlphaBoost, radius = radius, center = leftGradientCenter, center = leftOrUpGradientCenter, ) drawCircle( brush = rightBrush, brush = rightOrDownBrush, alpha = smartScrimAlpha + smartScrimAlphaBoost, radius = radius, center = rightGradientCenter, center = rightOrDownGradientCenter, ) } } Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/AmbientCueContainer.kt +8 −2 Original line number Diff line number Diff line Loading @@ -179,7 +179,11 @@ private fun TaskBarAnd3ButtonAmbientCue( translationY = pillCenter.y - size.height } else { if (rotation == ROTATION_90) { translationX = screenWidthPx - pillSize.height - size.width translationX = screenWidthPx - pillSize.width - size.width - LANDSCAPE_PADDING.dp.toPx() translationY = pillCenter.y - pillSize.width } else if (rotation == ROTATION_270) { translationX = pillSize.width Loading @@ -205,6 +209,7 @@ private fun TaskBarAnd3ButtonAmbientCue( portrait = portrait, pillCenter = pillCenter, pillWidth = pillSize.width, pillHeight = pillSize.height, rotation = rotation, taskBarMode = largeScreen, ) Loading @@ -224,7 +229,7 @@ private fun TaskBarAnd3ButtonAmbientCue( Modifier.graphicsLayer { translationX = pillCenter.x - size.width / 2 translationY = pillCenter.y - size.height / 2 pillSize = size pillSize = Size(pillPositionInWindow.width, pillPositionInWindow.height) } .onGloballyPositioned { layoutCoordinates -> layoutCoordinates.parentCoordinates?.let { parentCoordinates -> Loading Loading @@ -321,3 +326,4 @@ private const val SHORT_PILL_ACTIONS_VERTICAL_PADDING = 38 private const val NAV_BAR_ACTIONS_PADDING = NAV_BAR_HEIGHT_DP + 24 private const val ACTIONS_HORIZONTAL_PADDING = 32 private const val ACTIONS_TOP_PADDING = 42 private const val LANDSCAPE_PADDING = 65 Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/ActionList.kt +102 −14 Original line number Diff line number Diff line Loading @@ -99,8 +99,9 @@ fun ActionList( padding: PaddingValues = PaddingValues(0.dp), horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, portrait: Boolean = true, pillCenter: Offset = Offset.Unspecified, pillCenter: Offset = Offset.Zero, pillWidth: Float = 0f, pillHeight: Float = 0f, rotation: Int = 0, taskBarMode: Boolean = false, ) { Loading @@ -111,6 +112,7 @@ fun ActionList( val minGradientHeight = 70.dp val scrimVerticalPadding = 32.dp val scrimHorizontalPadding = 42.dp val landscapeMode = !portrait && !taskBarMode val smartScrimAlpha by animateFloatAsState( if (expanded) { Loading @@ -127,9 +129,11 @@ fun ActionList( val translateStiffnessMultiplier = 50 val overscrollStiffness = 2063f var containerHeightPx by remember { mutableIntStateOf(0) } var containerWidthPx by remember { mutableIntStateOf(0) } var radius by remember { mutableFloatStateOf(0f) } var wasEverExpanded by remember { mutableStateOf(false) } var actionListCenterPositionX by remember { mutableFloatStateOf(0f) } var actionListCenterPositionY by remember { mutableFloatStateOf(0f) } LaunchedEffect(expanded) { if (expanded) { Loading Loading @@ -225,6 +229,54 @@ fun ActionList( label = "scrimOffsetY", ) val landscapeScrimOffsetX by animateFloatAsState( targetValue = if (!expanded) containerWidthPx.toFloat() + pillWidth else containerWidthPx / 2f, animationSpec = if (expanded || wasEverExpanded) { // Enable animation only when user expands/collapses the action list. tween( durationMillis = 250, // Usually, 200 ms delay is used. But the collapsed delay is reduced to be // 100 ms to ensure the Action chips and background glow disappear at the // same pace. delayMillis = if (expanded) 200 else 100, ) } else { // Disable animation during Compose initialization. snap() }, label = "landscapeScrimOffsetX", ) var landscapeCollapsedScrimOffsetY by remember { mutableFloatStateOf(0f) } val landscapeScrimOffsetY by animateFloatAsState( targetValue = if (!expanded) landscapeCollapsedScrimOffsetY else containerHeightPx / 2f, animationSpec = if (expanded || wasEverExpanded) { // Enable animation only when user expands/collapses the action list. tween(250, delayMillis = 200) } else { // Disable animation during Compose initialization. snap() }, label = "landscapeScrimOffsetY", ) val landscapeScaleX by animateFloatAsState( targetValue = if (!expanded) 0.15f else 1f, animationSpec = tween( durationMillis = 250, // Usually, 200 ms delay is used. But the collapsed delay is reduced to be 100 // ms to ensure the Action chips and background glow disappear at the same pace. delayMillis = if (expanded) 200 else 100, ), label = "landscapeScaleX", ) LaunchedEffect(visible, expanded) { anchoredDraggableState.animateTo(if (visible && expanded) End else Start) } Loading Loading @@ -296,8 +348,11 @@ fun ActionList( ) .onGloballyPositioned { layoutCoordinates -> containerHeightPx = layoutCoordinates.size.height containerWidthPx = layoutCoordinates.size.width actionListCenterPositionX = layoutCoordinates.positionInWindow().x + layoutCoordinates.size.width / 2 actionListCenterPositionY = layoutCoordinates.positionInWindow().y + layoutCoordinates.size.height / 2 anchoredDraggableState.updateAnchors( DraggableAnchors { Start at 0f // Hidden Loading @@ -317,36 +372,69 @@ fun ActionList( val minScaleY = minGradientHeightPx / (radius * 2f) val scaleY = max(minScaleY, size.height / (radius * 2f) * scrimProgress) scale(scaleX = 1f, scaleY = scaleY, pivot = Offset(0f, size.height)) { val leftGradientCenter = scale( scaleX = if (!landscapeMode) 1f else landscapeScaleX, scaleY = scaleY, pivot = Offset(0f, if (!landscapeMode) size.height else 0f), ) { landscapeCollapsedScrimOffsetY = size.height / 2 + pillCenter.y - actionListCenterPositionY val safeScaleY = if (scaleY == 0f || scaleY.isNaN()) 1f else scaleY val safeScaleX = if (landscapeScaleX == 0f || landscapeScaleX.isNaN()) 1f else landscapeScaleX val leftOrUpGradientCenter = if (!landscapeMode) { Offset(size.width / 2 - sidePaddingPx, scrimOffsetY) val rightGradientCenter = } else { Offset( if (rotation == ROTATION_90) { landscapeScrimOffsetX / safeScaleX } else { (containerWidthPx - landscapeScrimOffsetX) / safeScaleX }, (landscapeScrimOffsetY - pillHeight / 2) / safeScaleY, ) } val rightOrDownGradientCenter = if (!landscapeMode) { Offset(size.width / 2 + sidePaddingPx, scrimOffsetY) val leftBrush = } else { Offset( if (rotation == ROTATION_90) { landscapeScrimOffsetX / safeScaleX } else { (containerWidthPx - landscapeScrimOffsetX) / safeScaleX }, (landscapeScrimOffsetY + pillHeight / 2) / safeScaleY, ) } val leftOrUpBrush = Brush.radialGradient( colors = listOf(leftGradientColor, leftGradientColor.copy(alpha = 0f)), center = leftGradientCenter, center = leftOrUpGradientCenter, radius = radius, ) val rightBrush = val rightOrDownBrush = Brush.radialGradient( colors = listOf(rightGradientColor, rightGradientColor.copy(alpha = 0f)), center = rightGradientCenter, center = rightOrDownGradientCenter, radius = radius * 0.85f, ) drawCircle( brush = leftBrush, brush = leftOrUpBrush, alpha = smartScrimAlpha + smartScrimAlphaBoost, radius = radius, center = leftGradientCenter, center = leftOrUpGradientCenter, ) drawCircle( brush = rightBrush, brush = rightOrDownBrush, alpha = smartScrimAlpha + smartScrimAlphaBoost, radius = radius, center = rightGradientCenter, center = rightOrDownGradientCenter, ) } } Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/AmbientCueContainer.kt +8 −2 Original line number Diff line number Diff line Loading @@ -179,7 +179,11 @@ private fun TaskBarAnd3ButtonAmbientCue( translationY = pillCenter.y - size.height } else { if (rotation == ROTATION_90) { translationX = screenWidthPx - pillSize.height - size.width translationX = screenWidthPx - pillSize.width - size.width - LANDSCAPE_PADDING.dp.toPx() translationY = pillCenter.y - pillSize.width } else if (rotation == ROTATION_270) { translationX = pillSize.width Loading @@ -205,6 +209,7 @@ private fun TaskBarAnd3ButtonAmbientCue( portrait = portrait, pillCenter = pillCenter, pillWidth = pillSize.width, pillHeight = pillSize.height, rotation = rotation, taskBarMode = largeScreen, ) Loading @@ -224,7 +229,7 @@ private fun TaskBarAnd3ButtonAmbientCue( Modifier.graphicsLayer { translationX = pillCenter.x - size.width / 2 translationY = pillCenter.y - size.height / 2 pillSize = size pillSize = Size(pillPositionInWindow.width, pillPositionInWindow.height) } .onGloballyPositioned { layoutCoordinates -> layoutCoordinates.parentCoordinates?.let { parentCoordinates -> Loading Loading @@ -321,3 +326,4 @@ private const val SHORT_PILL_ACTIONS_VERTICAL_PADDING = 38 private const val NAV_BAR_ACTIONS_PADDING = NAV_BAR_HEIGHT_DP + 24 private const val ACTIONS_HORIZONTAL_PADDING = 32 private const val ACTIONS_TOP_PADDING = 42 private const val LANDSCAPE_PADDING = 65