diff options
3 files changed, 63 insertions, 61 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt index 2bbe9b8fc20a..ff1cbd6b04c3 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt @@ -39,11 +39,11 @@ import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.layout.LayoutCoordinates +import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.integerResource -import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import com.android.compose.animation.Easings import com.android.compose.modifiers.thenIf @@ -79,12 +79,6 @@ internal fun PatternBouncer( val lineColor = MaterialTheme.colorScheme.primary val lineStrokeWidth = with(LocalDensity.current) { LINE_STROKE_WIDTH_DP.dp.toPx() } - var containerSize: IntSize by remember { mutableStateOf(IntSize(0, 0)) } - val horizontalSpacing = containerSize.width / colCount - val verticalSpacing = containerSize.height / rowCount - val spacing = min(horizontalSpacing, verticalSpacing).toFloat() - val verticalOffset = containerSize.height - spacing * rowCount - // All dots that should be rendered on the grid. val dots: List<PatternDotViewModel> by viewModel.dots.collectAsState() // The most recently selected dot, if the user is currently dragging. @@ -195,13 +189,14 @@ internal fun PatternBouncer( // This is the position of the input pointer. var inputPosition: Offset? by remember { mutableStateOf(null) } + var gridCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) } Canvas( modifier // Need to clip to bounds to make sure that the lines don't follow the input pointer // when it leaves the bounds of the dot grid. .clipToBounds() - .onSizeChanged { containerSize = it } + .onGloballyPositioned { coordinates -> gridCoordinates = coordinates } .thenIf(isInputEnabled) { Modifier.pointerInput(Unit) { awaitEachGesture { @@ -232,62 +227,72 @@ internal fun PatternBouncer( viewModel.onDrag( xPx = change.position.x, yPx = change.position.y, - containerSizePx = containerSize.width, - verticalOffsetPx = verticalOffset, + containerSizePx = size.width, ) } } } ) { - if (isAnimationEnabled) { - // Draw lines between dots. - selectedDots.forEachIndexed { index, dot -> - if (index > 0) { - val previousDot = selectedDots[index - 1] - val lineFadeOutAnimationProgress = lineFadeOutAnimatables[previousDot]!!.value - val startLerp = 1 - lineFadeOutAnimationProgress - val from = pixelOffset(previousDot, spacing, verticalOffset) - val to = pixelOffset(dot, spacing, verticalOffset) - val lerpedFrom = - Offset( - x = from.x + (to.x - from.x) * startLerp, - y = from.y + (to.y - from.y) * startLerp, + gridCoordinates?.let { nonNullCoordinates -> + val containerSize = nonNullCoordinates.size + val horizontalSpacing = containerSize.width.toFloat() / colCount + val verticalSpacing = containerSize.height.toFloat() / rowCount + val spacing = min(horizontalSpacing, verticalSpacing) + val verticalOffset = containerSize.height - spacing * rowCount + + if (isAnimationEnabled) { + // Draw lines between dots. + selectedDots.forEachIndexed { index, dot -> + if (index > 0) { + val previousDot = selectedDots[index - 1] + val lineFadeOutAnimationProgress = + lineFadeOutAnimatables[previousDot]!!.value + val startLerp = 1 - lineFadeOutAnimationProgress + val from = pixelOffset(previousDot, spacing, verticalOffset) + val to = pixelOffset(dot, spacing, verticalOffset) + val lerpedFrom = + Offset( + x = from.x + (to.x - from.x) * startLerp, + y = from.y + (to.y - from.y) * startLerp, + ) + drawLine( + start = lerpedFrom, + end = to, + cap = StrokeCap.Round, + alpha = lineFadeOutAnimationProgress * lineAlpha(spacing), + color = lineColor, + strokeWidth = lineStrokeWidth, ) - drawLine( - start = lerpedFrom, - end = to, - cap = StrokeCap.Round, - alpha = lineFadeOutAnimationProgress * lineAlpha(spacing), - color = lineColor, - strokeWidth = lineStrokeWidth, - ) + } } - } - // Draw the line between the most recently-selected dot and the input pointer position. - inputPosition?.let { lineEnd -> - currentDot?.let { dot -> - val from = pixelOffset(dot, spacing, verticalOffset) - val lineLength = sqrt((from.y - lineEnd.y).pow(2) + (from.x - lineEnd.x).pow(2)) - drawLine( - start = from, - end = lineEnd, - cap = StrokeCap.Round, - alpha = lineAlpha(spacing, lineLength), - color = lineColor, - strokeWidth = lineStrokeWidth, - ) + // Draw the line between the most recently-selected dot and the input pointer + // position. + inputPosition?.let { lineEnd -> + currentDot?.let { dot -> + val from = pixelOffset(dot, spacing, verticalOffset) + val lineLength = + sqrt((from.y - lineEnd.y).pow(2) + (from.x - lineEnd.x).pow(2)) + drawLine( + start = from, + end = lineEnd, + cap = StrokeCap.Round, + alpha = lineAlpha(spacing, lineLength), + color = lineColor, + strokeWidth = lineStrokeWidth, + ) + } } } - } - // Draw each dot on the grid. - dots.forEach { dot -> - drawCircle( - center = pixelOffset(dot, spacing, verticalOffset), - color = dotColor, - radius = dotRadius * (dotScalingAnimatables[dot]?.value ?: 1f), - ) + // Draw each dot on the grid. + dots.forEach { dot -> + drawCircle( + center = pixelOffset(dot, spacing, verticalOffset), + color = dotColor, + radius = dotRadius * (dotScalingAnimatables[dot]?.value ?: 1f), + ) + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt index ed6a48f93d67..b1c5ab6122fe 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt @@ -94,24 +94,23 @@ class PatternBouncerViewModel( * @param yPx The vertical coordinate of the position of the user's pointer, in pixels. * @param containerSizePx The size of the container of the dot grid, in pixels. It's assumed * that the dot grid is perfectly square such that width and height are equal. - * @param verticalOffsetPx How far down from `0` does the dot grid start on the display. */ - fun onDrag(xPx: Float, yPx: Float, containerSizePx: Int, verticalOffsetPx: Float) { + fun onDrag(xPx: Float, yPx: Float, containerSizePx: Int) { val cellWidthPx = containerSizePx / columnCount val cellHeightPx = containerSizePx / rowCount - if (xPx < 0 || yPx < verticalOffsetPx) { + if (xPx < 0 || yPx < 0) { return } val dotColumn = (xPx / cellWidthPx).toInt() - val dotRow = ((yPx - verticalOffsetPx) / cellHeightPx).toInt() + val dotRow = (yPx / cellHeightPx).toInt() if (dotColumn > columnCount - 1 || dotRow > rowCount - 1) { return } val dotPixelX = dotColumn * cellWidthPx + cellWidthPx / 2 - val dotPixelY = dotRow * cellHeightPx + cellHeightPx / 2 + verticalOffsetPx + val dotPixelY = dotRow * cellHeightPx + cellHeightPx / 2 val distance = sqrt((xPx - dotPixelX).pow(2) + (yPx - dotPixelY).pow(2)) val hitRadius = hitFactor * min(cellWidthPx, cellHeightPx) / 2 diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt index 125fe680db21..862c39c9d4cc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt @@ -322,7 +322,6 @@ class PatternBouncerViewModelTest : SysuiTestCase() { xPx = 30f * coordinate.x + 15, yPx = 30f * coordinate.y + 15, containerSizePx = 90, - verticalOffsetPx = 0f, ) } @@ -369,7 +368,6 @@ class PatternBouncerViewModelTest : SysuiTestCase() { xPx = dotSize * coordinate.x + 15f, yPx = dotSize * coordinate.y + 15f, containerSizePx = containerSize, - verticalOffsetPx = 0f, ) } |