Add animated chain demo

Added demo that takes advantage of the improved handling of
ConstraintSet with `animateChanges = true`.

Bug: n/a
Test: n/a
Change-Id: Iad16fb96994db8e3d640e2d6a19d010add07a0fc
diff --git a/constraintlayout/constraintlayout-compose/integration-tests/constraintlayout-compose-demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt b/constraintlayout/constraintlayout-compose/integration-tests/constraintlayout-compose-demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt
new file mode 100644
index 0000000..20dacf6
--- /dev/null
+++ b/constraintlayout/constraintlayout-compose/integration-tests/constraintlayout-compose-demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.constraintlayout.compose.demos
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.Icon
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowBack
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+
+data class ComposeDemo(val title: String, val content: @Composable () -> Unit)
+
+val AllComposeConstraintLayoutDemos: List<ComposeDemo> =
+    listOf(
+        ComposeDemo("CustomColorInKeyAttributes") { CustomColorInKeyAttributesDemo() },
+        ComposeDemo("SimpleOnSwipe") { SimpleOnSwipe() },
+        ComposeDemo("AnimatedChainOrientation") { ChainsAnimatedOrientationDemo() }
+    )
+
+/**
+ * Main screen to explore and interact with all demos from [AllComposeConstraintLayoutDemos].
+ */
+@Preview
+@Composable
+fun ComposeConstraintLayoutDemos() {
+    var displayedDemo by remember { mutableStateOf<ComposeDemo?>(null) }
+    Column {
+        Column {
+            displayedDemo?.let {
+                // Header with back button
+                Row(
+                    modifier = Modifier
+                        .fillMaxWidth()
+                        .height(50.dp)
+                        .background(Color.White)
+                        .graphicsLayer(shadowElevation = 2f)
+                        .clickable { displayedDemo = null }, // Return to list of demos
+                    verticalAlignment = Alignment.CenterVertically
+                ) {
+                    Icon(imageVector = Icons.Default.ArrowBack, contentDescription = "Back")
+                    Text(text = it.title)
+                }
+            } ?: kotlin.run {
+                // Main Title
+                Text(text = "ComposeConstraintLayoutDemos", style = MaterialTheme.typography.h6)
+                Spacer(modifier = Modifier.height(8.dp))
+            }
+        }
+        Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
+            displayedDemo?.let { demo ->
+                // Display selected demo
+                Box(
+                    Modifier
+                        .fillMaxWidth()
+                        .weight(1.0f, true)
+                ) {
+                    demo.content()
+                }
+            } ?: kotlin.run {
+                // Display list of demos
+                AllComposeConstraintLayoutDemos.forEach {
+                    ComposeDemoItem(it.title) { displayedDemo = it }
+                }
+            }
+        }
+    }
+}
+
+@Composable
+private fun ComposeDemoItem(title: String, modifier: Modifier = Modifier, onClick: () -> Unit) {
+    Box(
+        modifier = modifier
+            .padding(horizontal = 8.dp)
+            .fillMaxWidth()
+            .height(44.dp)
+            .clip(RoundedCornerShape(10.dp))
+            .background(Color.White)
+            .clickable(onClick = onClick)
+            .padding(start = 8.dp),
+        contentAlignment = Alignment.CenterStart
+    ) {
+        Text(
+            text = title,
+            modifier = Modifier,
+            fontSize = 16.sp
+        )
+    }
+}
\ No newline at end of file
diff --git a/constraintlayout/constraintlayout-compose/integration-tests/constraintlayout-compose-demos/src/main/java/androidx/constraintlayout/compose/demos/ChainsDemo.kt b/constraintlayout/constraintlayout-compose/integration-tests/constraintlayout-compose-demos/src/main/java/androidx/constraintlayout/compose/demos/ChainsDemo.kt
new file mode 100644
index 0000000..5611bc4
--- /dev/null
+++ b/constraintlayout/constraintlayout-compose/integration-tests/constraintlayout-compose-demos/src/main/java/androidx/constraintlayout/compose/demos/ChainsDemo.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.constraintlayout.compose.demos
+
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.material.Button
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.layoutId
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.constraintlayout.compose.ConstraintLayout
+import androidx.constraintlayout.compose.ConstraintSet
+import androidx.constraintlayout.compose.Dimension
+
+@Preview
+@Composable
+fun ChainsAnimatedOrientationDemo() {
+    val boxColors = listOf(Color.Red, Color.Blue, Color.Green)
+    var isHorizontal by remember { mutableStateOf(true) }
+
+    Column(Modifier.fillMaxSize()) {
+        ConstraintLayout(
+            constraintSet = ConstraintSet {
+                val (box0, box1, box2) = createRefsFor("box0", "box1", "box2")
+                box1.withChainParams(8.dp, 8.dp, 8.dp, 8.dp)
+
+                if (isHorizontal) {
+                    constrain(box0, box1, box2) {
+                        width = Dimension.fillToConstraints
+                        height = Dimension.value(20.dp)
+                        centerVerticallyTo(parent)
+                    }
+                    constrain(box1) {
+                        // Override height to be a ratio
+                        height = Dimension.ratio("2:1")
+                    }
+
+                    createHorizontalChain(box0, box1, box2)
+                } else {
+                    constrain(box0, box1, box2) {
+                        width = Dimension.value(20.dp)
+                        height = Dimension.fillToConstraints
+                        centerHorizontallyTo(parent)
+                    }
+                    constrain(box1) {
+                        // Override width to be a ratio
+                        width = Dimension.ratio("2:1")
+                    }
+
+                    createVerticalChain(box0, box1, box2)
+                }
+            },
+            animateChanges = true,
+            animationSpec = tween(800),
+            modifier = Modifier
+                .fillMaxWidth()
+                .weight(1.0f, true)
+        ) {
+            boxColors.forEachIndexed { index, color ->
+                Box(
+                    modifier = Modifier
+                        .layoutId("box$index")
+                        .background(color)
+                )
+            }
+        }
+        Button(onClick = { isHorizontal = !isHorizontal }) {
+            Text(text = "Toggle Orientation")
+        }
+    }
+}
\ No newline at end of file