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

Commit 4767fdaa authored by Mike Schneider's avatar Mike Schneider
Browse files

Floating version of VerticalExpandContainerSpec

- Renames `EdgeContainerExpansion` into `VerticalExpandContainer`
- Adds a "floating" background
- Added the `isFloating` flag to the spec

Note: I'm not particularly fond of the isFloating flag, but want to a) experiment, and b) get b/401224916 fixed, hence moving forward with this solution. Will revisit.

Bug: 401224916
Test: ContentRevealTest
Flag: com.android.systemui.scene_container
Change-Id: I715f133933107e9b1b105bce5b8e22370ab1890c
parent 868534d2
Loading
Loading
Loading
Loading
+59 −5
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.mechanics.behavior

import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
@@ -34,19 +35,72 @@ import androidx.compose.ui.util.fastCoerceIn
import androidx.compose.ui.util.lerp
import kotlin.math.min

/**
 * Draws the background of a vertically container, and applies clipping to it.
 *
 * Intended to be used with a [VerticalExpandContainerSpec] motion.
 */
fun Modifier.verticalExpandContainerBackground(
    backgroundColor: Color,
    spec: VerticalExpandContainerSpec,
): Modifier =
    this.then(
        if (spec.isFloating) {
            Modifier.verticalFloatingExpandContainerBackground(backgroundColor, spec)
        } else {
            Modifier.verticalEdgeExpandContainerBackground(backgroundColor, spec)
        }
    )

/**
 * Draws the background of an floating container, and applies clipping to it.
 *
 * Intended to be used with a [VerticalExpandContainerSpec] motion.
 */
internal fun Modifier.verticalFloatingExpandContainerBackground(
    backgroundColor: Color,
    spec: VerticalExpandContainerSpec,
): Modifier =
    this.drawWithCache {
        val targetRadiusPx = spec.radius.toPx()
        val currentRadiusPx = min(targetRadiusPx, min(size.width, size.height) / 2f)
        val horizontalInset = targetRadiusPx - currentRadiusPx
        val shapeTopLeft = Offset(horizontalInset, 0f)
        val shapeSize = Size(size.width - (horizontalInset * 2f), size.height)

        val layer =
            obtainGraphicsLayer().apply {
                clip = true
                setRoundRectOutline(shapeTopLeft, shapeSize, cornerRadius = currentRadiusPx)

                record { drawContent() }
            }

        onDrawWithContent {
            drawRoundRect(
                color = backgroundColor,
                topLeft = shapeTopLeft,
                size = shapeSize,
                cornerRadius = CornerRadius(currentRadiusPx),
            )

            drawLayer(layer)
        }
    }

/**
 * Draws the background of an edge container, and applies clipping to it.
 *
 * Intended to be used with a [EdgeContainerExpansionSpec] motion.
 * Intended to be used with a [VerticalExpandContainerSpec] motion.
 */
fun Modifier.edgeContainerExpansionBackground(
internal fun Modifier.verticalEdgeExpandContainerBackground(
    backgroundColor: Color,
    spec: EdgeContainerExpansionSpec,
    spec: VerticalExpandContainerSpec,
): Modifier = this.then(EdgeContainerExpansionBackgroundElement(backgroundColor, spec))

internal class EdgeContainerExpansionBackgroundNode(
    var backgroundColor: Color,
    var spec: EdgeContainerExpansionSpec,
    var spec: VerticalExpandContainerSpec,
) : Modifier.Node(), DrawModifierNode {

    private var graphicsLayer: GraphicsLayer? = null
@@ -126,7 +180,7 @@ internal class EdgeContainerExpansionBackgroundNode(

private data class EdgeContainerExpansionBackgroundElement(
    val backgroundColor: Color,
    val spec: EdgeContainerExpansionSpec,
    val spec: VerticalExpandContainerSpec,
) : ModifierNodeElement<EdgeContainerExpansionBackgroundNode>() {
    override fun create(): EdgeContainerExpansionBackgroundNode =
        EdgeContainerExpansionBackgroundNode(backgroundColor, spec)
+14 −10
Original line number Diff line number Diff line
@@ -34,19 +34,21 @@ import com.android.mechanics.spec.MotionSpec
import com.android.mechanics.spec.OnChangeSegmentHandler
import com.android.mechanics.spec.SegmentData
import com.android.mechanics.spec.SegmentKey
import com.android.mechanics.spec.buildDirectionalMotionSpec
import com.android.mechanics.spec.builder
import com.android.mechanics.spec.reverseBuilder
import com.android.mechanics.spring.SpringParameters

/** Motion spec for a vertically expandable container. */
class EdgeContainerExpansionSpec(
class VerticalExpandContainerSpec(
    val isFloating: Boolean,
    val minRadius: Dp = Defaults.MinRadius,
    val radius: Dp = Defaults.Radius,
    val visibleHeight: Dp = Defaults.VisibleHeight,
    val preDetachRatio: Float = Defaults.PreDetachRatio,
    val detachHeight: Dp = Defaults.DetachHeight,
    val attachHeight: Dp = Defaults.AttachHeight,
    val detachHeight: Dp = if (isFloating) radius * 3 else Defaults.DetachHeight,
    val attachHeight: Dp = if (isFloating) radius * 2 else Defaults.AttachHeight,
    val widthOffset: Dp = Defaults.WidthOffset,
    val minRadius: Dp = Defaults.MinRadius,
    val radius: Dp = Defaults.Radius,
    val attachSpring: SpringParameters = Defaults.AttachSpring,
    val detachSpring: SpringParameters = Defaults.DetachSpring,
    val opacitySpring: SpringParameters = Defaults.OpacitySpring,
@@ -99,14 +101,16 @@ class EdgeContainerExpansionSpec(
        density: Density,
    ): MotionSpec {
        return with(density) {
            MotionSpec.builder(
                    SpringParameters(motionScheme.defaultSpatialSpec()),
                    initialMapping = { input ->
            if (isFloating) {
                MotionSpec(buildDirectionalMotionSpec(Mapping.Fixed(intrinsicWidth)))
            } else {
                MotionSpec(
                    buildDirectionalMotionSpec({ input ->
                        val fraction = (input / detachHeight.toPx()).fastCoerceIn(0f, 1f)
                        intrinsicWidth - lerp(widthOffset.toPx(), 0f, fraction)
                    },
                    })
                )
                .complete()
            }
        }
    }