summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt113
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt2
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,
)
}