Showing PositionIndicator by default and showing it on size or position changes when AutoHide visibility is used.

PositionIndicator is now shown by default when it's used with scrollable content. Before by default it was invisible, and was showing only after scrollable was scrolled. PositionIndicatorVisibility.AutoHide now shows PositionIndicator when size or position change and after delay fades it away

Bug: 304717932
Test: PositionIndicatorTest.kt
Relnote: "PositionIndicator is now shown by default when it's used with scrollable content. PositionIndicatorVisibility.AutoHide now shows PositionIndicator when size or position change"
Change-Id: I7491e44150cdd4cd594315552b4a6279d792258a
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt
index 54b69b3..a1c0393 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt
@@ -172,7 +172,7 @@
     }
 
     @Test
-    fun positionIndicatorWithScalingLazyColumn_hidden_by_default() {
+    fun positionIndicatorWithScalingLazyColumn_shown_by_default() {
         lateinit var state: ScalingLazyListState
         lateinit var positionIndicatorState: PositionIndicatorState
         val piColor = Color.Yellow
@@ -200,7 +200,7 @@
         }
         rule.waitForIdle()
         rule.onNodeWithTag(TEST_TAG).captureToImage()
-            .assertDoesNotContainColor(piColor)
+            .assertContainsColor(expectedColor = piColor, minPercent = 0.2f)
     }
 
     @Test
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt
index 3c8f1bf..916c008 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt
@@ -714,7 +714,9 @@
     val updatedPositionAnimationSpec by rememberUpdatedState(positionAnimationSpec)
 
     LaunchedEffect(state) {
-        var beforeFirstAnimation = true
+        // We don't want to trigger first animation when we receive position or size
+        // for the first time, because initial position and size are equal to 0.
+        var skipFirstPositionAnimation = true
 
         // Skip first alpha animation only when initial visibility is not Hide
         var skipFirstAlphaAnimation = state.visibility(containerSize.height.toFloat()) !=
@@ -730,10 +732,22 @@
                     state.visibility(containerSize.height.toFloat())
                 )
             }.collectLatest {
-                if (beforeFirstAnimation || updatedPositionAnimationSpec is SnapSpec) {
+                // Workaround for b/315149417. When visibility is Hide and other values equal to 0,
+                // we consider that as non-initialized state.
+                // It means that we skip first alpha animation, and also ignore these values.
+                if (skipFirstPositionAnimation &&
+                    it.visibility == PositionIndicatorVisibility.Hide &&
+                    it.position == 0f &&
+                    it.size == 0f
+                ) {
+                    skipFirstAlphaAnimation = true
+                    return@collectLatest
+                }
+
+                if (skipFirstPositionAnimation || updatedPositionAnimationSpec is SnapSpec) {
                     sizeFractionAnimatable.snapTo(it.size)
                     positionFractionAnimatable.snapTo(it.position)
-                    beforeFirstAnimation = false
+                    skipFirstPositionAnimation = false
                 } else {
                     launch {
                         sizeFractionAnimatable
@@ -764,7 +778,9 @@
                         handleFadeOut(updatedFadeOutAnimationSpec, animateAlphaChannel, alphaValue)
                     }
 
-                    PositionIndicatorVisibility.Show -> {
+                    // PositionIndicatorVisibility.Show and
+                    // PositionIndicatorVisibility.AutoHide cases
+                    else -> {
                         // If fadeInAnimationSpec is SnapSpec or we skip the first animation,
                         // then we change alphaValue directly here
                         if (updatedFadeInAnimationSpec is SnapSpec || skipFirstAlphaAnimation) {
@@ -774,11 +790,6 @@
                             // Otherwise we send an event to animation channel
                             animateAlphaChannel.trySend(1f)
                         }
-                    }
-
-                    // PositionIndicatorVisibility.AutoHide case
-                    else -> {
-                        skipFirstAlphaAnimation = false
 
                         if (it.visibility == PositionIndicatorVisibility.AutoHide) {
                             // Waiting for 2000ms and changing alpha value to 0f
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.android.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.android.kt
index 253f341..48d70a8 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.android.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.android.kt
@@ -196,7 +196,6 @@
                         Vignette(vignettePosition = VignettePosition.TopAndBottom)
                     }
                 },
-                positionIndicator = positionIndicator,
                 modifier = modifier,
             ) {
                 SwipeToDismissBox(
@@ -212,13 +211,16 @@
                         transitionState = MutableTransitionState(DialogVisibility.Hide)
                     }
                 ) { isBackground ->
-                    Box(
-                        modifier = Modifier
-                            .matchParentSize()
-                            .graphicsLayer(alpha = contentAlpha)
-                            .background(MaterialTheme.colors.background)
-                    ) {
-                        if (!isBackground) content()
+                    if (!isBackground) {
+                        Box(
+                            modifier = Modifier
+                                .matchParentSize()
+                                .graphicsLayer(alpha = contentAlpha)
+                                .background(MaterialTheme.colors.background)
+                        ) {
+                            content()
+                            positionIndicator()
+                        }
                     }
                 }
             }
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
index f4dabe1..317dc43 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
@@ -642,9 +642,12 @@
             "Position Indicator",
             listOf(
                 ComposableDemo("Hide when no scrollable") { HideWhenFullDemo() },
-                ComposableDemo("Hide when no scrollable on ScalingLazyColumn") {
+                ComposableDemo("Hide when no scrollable SLC") {
                     HideWhenFullSLCDemo()
                 },
+                ComposableDemo("SLC with PositionIndicator") {
+                    SLCWithPositionIndicatorDemo()
+                },
                 ComposableDemo("Controllable PI") { ControllablePositionIndicator() },
                 ComposableDemo("Shared PI") { SharedPositionIndicator() }
             )
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PositionIndicatorDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PositionIndicatorDemos.kt
index c5a25a1..780a7c7 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PositionIndicatorDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PositionIndicatorDemos.kt
@@ -112,6 +112,33 @@
 }
 
 @Composable
+fun SLCWithPositionIndicatorDemo() {
+    val listState = rememberScalingLazyListState(5)
+    Scaffold(
+        positionIndicator = {
+            PositionIndicator(
+                scalingLazyListState = listState,
+                modifier = Modifier
+            )
+        }
+    ) {
+        ScalingLazyColumn(
+            state = listState,
+            autoCentering = null
+        ) {
+            items(
+                count = 15
+            ) {
+                Chip(
+                    onClick = {},
+                    label = { Text("SLC Item #$it") }
+                )
+            }
+        }
+    }
+}
+
+@Composable
 fun ControllablePositionIndicator() {
     val position = remember { mutableFloatStateOf(0.2f) }
     val size = remember { mutableFloatStateOf(0.5f) }