Deprecate LazyColumnFor, LazyRowFor, LazyColumnForIndexed and LazyRowForIndexed

Test: existing tests
Relnote: Deprecate LazyColumnFor, LazyRowFor, LazyColumnForIndexed and LazyRowForIndexed. Use LazyColumn and LazyRow instead
Change-Id: I5b48c8a3b1fef2f603ab69ded1d19709aa9f87fb
diff --git a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimatedVisiblilityLazyColumnDemo.kt b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimatedVisiblilityLazyColumnDemo.kt
index d28cb90..2d1b4b4 100644
--- a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimatedVisiblilityLazyColumnDemo.kt
+++ b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimatedVisiblilityLazyColumnDemo.kt
@@ -27,7 +27,7 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.lazy.LazyColumnForIndexed
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.material.Button
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
@@ -62,13 +62,15 @@
                 Text("Remove")
             }
         }
-        LazyColumnForIndexed(turquoiseColors) { i, color ->
-            AnimatedVisibility(
-                (turquoiseColors.size - itemNum) <= i,
-                enter = expandVertically(),
-                exit = shrinkVertically()
-            ) {
-                Spacer(Modifier.fillMaxWidth().height(90.dp).background(color))
+        LazyColumn {
+            itemsIndexed(turquoiseColors) { i, color ->
+                AnimatedVisibility(
+                    (turquoiseColors.size - itemNum) <= i,
+                    enter = expandVertically(),
+                    exit = shrinkVertically()
+                ) {
+                    Spacer(Modifier.fillMaxWidth().height(90.dp).background(color))
+                }
             }
         }
 
diff --git a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/EnterExitTransitionDemo.kt b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/EnterExitTransitionDemo.kt
index d5b30d9..4e85b17 100644
--- a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/EnterExitTransitionDemo.kt
+++ b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/EnterExitTransitionDemo.kt
@@ -37,7 +37,7 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.preferredHeight
 import androidx.compose.foundation.layout.wrapContentWidth
-import androidx.compose.foundation.lazy.LazyColumnFor
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.selection.selectable
 import androidx.compose.material.Button
 import androidx.compose.material.Checkbox
@@ -224,11 +224,10 @@
                     }
                 }
             }
-            LazyColumnFor(
-                menuText,
-                modifier = Modifier.fillMaxSize().background(Color(0xFFd8c7ff))
-            ) {
-                Text(it, Modifier.padding(5.dp))
+            LazyColumn(Modifier.fillMaxSize().background(Color(0xFFd8c7ff))) {
+                items(menuText) {
+                    Text(it, Modifier.padding(5.dp))
+                }
             }
         }
     }
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index 542f765..833d3c5 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -325,10 +325,10 @@
   }
 
   public final class LazyForKt {
-    method @androidx.compose.runtime.Composable public static <T> void LazyColumnFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static <T> void LazyColumnForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static <T> void LazyRowFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static <T> void LazyRowForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyColumnFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyColumnForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyRowFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyRowForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
   }
 
   public final class LazyGridKt {
diff --git a/compose/foundation/foundation/api/public_plus_experimental_current.txt b/compose/foundation/foundation/api/public_plus_experimental_current.txt
index 542f765..833d3c5 100644
--- a/compose/foundation/foundation/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation/api/public_plus_experimental_current.txt
@@ -325,10 +325,10 @@
   }
 
   public final class LazyForKt {
-    method @androidx.compose.runtime.Composable public static <T> void LazyColumnFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static <T> void LazyColumnForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static <T> void LazyRowFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static <T> void LazyRowForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyColumnFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyColumnForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyRowFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyRowForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
   }
 
   public final class LazyGridKt {
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index 542f765..833d3c5 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -325,10 +325,10 @@
   }
 
   public final class LazyForKt {
-    method @androidx.compose.runtime.Composable public static <T> void LazyColumnFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static <T> void LazyColumnForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static <T> void LazyRowFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static <T> void LazyRowForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyColumnFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyColumnForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyRowFor(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super T,kotlin.Unit> itemContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T> void LazyRowForIndexed(java.util.List<? extends T> items, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, kotlin.jvm.functions.Function3<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,? super T,kotlin.Unit> itemContent);
   }
 
   public final class LazyGridKt {
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ListDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ListDemos.kt
index ec4fd27..d3d049e 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ListDemos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ListDemos.kt
@@ -36,11 +36,7 @@
 import androidx.compose.foundation.layout.preferredWidth
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.LazyColumnFor
-import androidx.compose.foundation.lazy.LazyColumnForIndexed
 import androidx.compose.foundation.lazy.LazyRow
-import androidx.compose.foundation.lazy.LazyRowFor
-import androidx.compose.foundation.lazy.LazyRowForIndexed
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.shape.RoundedCornerShape
@@ -87,17 +83,19 @@
 
 @Composable
 private fun LazyColumnDemo() {
-    LazyColumnFor(
-        items = listOf(
-            "Hello,", "World:", "It works!", "",
-            "this one is really long and spans a few lines for scrolling purposes",
-            "these", "are", "offscreen"
-        ) + (1..100).map { "$it" }
-    ) {
-        Text(text = it, fontSize = 80.sp)
+    LazyColumn {
+        items(
+            items = listOf(
+                "Hello,", "World:", "It works!", "",
+                "this one is really long and spans a few lines for scrolling purposes",
+                "these", "are", "offscreen"
+            ) + (1..100).map { "$it" }
+        ) {
+            Text(text = it, fontSize = 80.sp)
 
-        if (it.contains("works")) {
-            Text("You can even emit multiple components per item.")
+            if (it.contains("works")) {
+                Text("You can even emit multiple components per item.")
+            }
         }
     }
 }
@@ -113,11 +111,10 @@
             Button(modifier = buttonModifier, onClick = { numItems-- }) { Text("Remove") }
             Button(modifier = buttonModifier, onClick = { offset++ }) { Text("Offset") }
         }
-        LazyColumnFor(
-            (1..numItems).map { it + offset }.toList(),
-            Modifier.fillMaxWidth()
-        ) {
-            Text("$it", style = AmbientTextStyle.current.copy(fontSize = 40.sp))
+        LazyColumn(Modifier.fillMaxWidth()) {
+            items((1..numItems).map { it + offset }.toList()) {
+                Text("$it", style = AmbientTextStyle.current.copy(fontSize = 40.sp))
+            }
         }
     }
 }
@@ -183,12 +180,13 @@
                 fontSize = 20.sp
             )
         }
-        LazyColumnFor(
-            (0..1000).toList(),
+        LazyColumn(
             Modifier.fillMaxWidth(),
             state = state
         ) {
-            Text("$it", style = AmbientTextStyle.current.copy(fontSize = 40.sp))
+            items((0..1000).toList()) {
+                Text("$it", style = AmbientTextStyle.current.copy(fontSize = 40.sp))
+            }
         }
     }
 }
@@ -207,8 +205,10 @@
 
 @Composable
 private fun LazyRowItemsDemo() {
-    LazyRowFor(items = (1..1000).toList()) {
-        Square(it)
+    LazyRow {
+        items((1..1000).toList()) {
+            Square(it)
+        }
     }
 }
 
@@ -227,11 +227,15 @@
 private fun ListWithIndexSample() {
     val friends = listOf("Alex", "John", "Danny", "Sam")
     Column {
-        LazyRowForIndexed(friends, Modifier.fillMaxWidth()) { index, friend ->
-            Text("$friend at index $index", Modifier.padding(16.dp))
+        LazyRow(Modifier.fillMaxWidth()) {
+            itemsIndexed(friends) { index, friend ->
+                Text("$friend at index $index", Modifier.padding(16.dp))
+            }
         }
-        LazyColumnForIndexed(friends, Modifier.fillMaxWidth()) { index, friend ->
-            Text("$friend at index $index", Modifier.padding(16.dp))
+        LazyColumn(Modifier.fillMaxWidth()) {
+            itemsIndexed(friends) { index, friend ->
+                Text("$friend at index $index", Modifier.padding(16.dp))
+            }
         }
     }
 }
@@ -239,14 +243,16 @@
 @Composable
 private fun RtlListDemo() {
     Providers(AmbientLayoutDirection provides LayoutDirection.Rtl) {
-        LazyRowForIndexed((0..100).toList(), Modifier.fillMaxWidth()) { index, item ->
-            Text(
-                "$item",
-                Modifier
-                    .size(100.dp)
-                    .background(if (index % 2 == 0) Color.LightGray else Color.Transparent)
-                    .padding(16.dp)
-            )
+        LazyRow(Modifier.fillMaxWidth()) {
+            itemsIndexed((0..100).toList()) { index, item ->
+                Text(
+                    "$item",
+                    Modifier
+                        .size(100.dp)
+                        .background(if (index % 2 == 0) Color.LightGray else Color.Transparent)
+                        .padding(16.dp)
+                )
+            }
         }
     }
 }
@@ -254,8 +260,10 @@
 @Composable
 private fun PagerLikeDemo() {
     val pages = listOf(Color.LightGray, Color.White, Color.DarkGray)
-    LazyRowFor(pages) {
-        Spacer(Modifier.fillParentMaxSize().background(it))
+    LazyRow {
+        items(pages) {
+            Spacer(Modifier.fillParentMaxSize().background(it))
+        }
     }
 }
 
@@ -457,8 +465,10 @@
     }
     LazyColumn {
         item {
-            LazyRowFor(List(100) { it }) {
-                item(it)
+            LazyRow {
+                items(List(100) { it }) {
+                    item(it)
+                }
             }
         }
         items(List(100) { it }) {
diff --git a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/LazyForSamples.kt b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/LazyForSamples.kt
deleted file mode 100644
index d1b87dd..0000000
--- a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/LazyForSamples.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2020 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.compose.foundation.samples
-
-import androidx.annotation.Sampled
-import androidx.compose.foundation.lazy.LazyColumnFor
-import androidx.compose.foundation.lazy.LazyColumnForIndexed
-import androidx.compose.foundation.lazy.LazyRowFor
-import androidx.compose.foundation.lazy.LazyRowForIndexed
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-
-@Sampled
-@Composable
-fun LazyColumnForSample() {
-    val items = listOf("A", "B", "C")
-    LazyColumnFor(items) {
-        Text("Item is $it")
-    }
-}
-
-@Sampled
-@Composable
-fun LazyRowForSample() {
-    val items = listOf("A", "B", "C")
-    LazyRowFor(items) {
-        Text("Item is $it")
-    }
-}
-
-@Sampled
-@Composable
-fun LazyColumnForIndexedSample() {
-    val items = listOf("A", "B", "C")
-    LazyColumnForIndexed(items) { index, item ->
-        Text("Item at index $index is $item")
-    }
-}
-
-@Sampled
-@Composable
-fun LazyRowForIndexedSample() {
-    val items = listOf("A", "B", "C")
-    LazyRowForIndexed(items) { index, item ->
-        Text("Item at index $index is $item")
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnForTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnForTest.kt
deleted file mode 100644
index bbd257b..0000000
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnForTest.kt
+++ /dev/null
@@ -1,1136 +0,0 @@
-/*
- * Copyright 2020 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.compose.foundation.lazy
-
-import androidx.compose.animation.core.ExponentialDecay
-import androidx.compose.animation.core.ManualAnimationClock
-import androidx.compose.animation.core.snap
-import androidx.compose.foundation.animation.FlingConfig
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.preferredHeight
-import androidx.compose.foundation.layout.preferredSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.sizeIn
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.text.BasicText
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.onCommit
-import androidx.compose.runtime.onDispose
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawBehind
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.gesture.TouchSlop
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.SemanticsNodeInteraction
-import androidx.compose.ui.test.assertCountEquals
-import androidx.compose.ui.test.assertHeightIsEqualTo
-import androidx.compose.ui.test.assertIsDisplayed
-import androidx.compose.ui.test.assertIsEqualTo
-import androidx.compose.ui.test.assertIsNotDisplayed
-import androidx.compose.ui.test.assertPositionInRootIsEqualTo
-import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
-import androidx.compose.ui.test.assertWidthIsEqualTo
-import androidx.compose.ui.test.center
-import androidx.compose.ui.test.click
-import androidx.compose.ui.test.getUnclippedBoundsInRoot
-import androidx.compose.ui.test.junit4.StateRestorationTester
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onChildren
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.onNodeWithText
-import androidx.compose.ui.test.performGesture
-import androidx.compose.ui.test.swipeUp
-import androidx.compose.ui.test.swipeWithVelocity
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.LargeTest
-import com.google.common.collect.Range
-import com.google.common.truth.IntegerSubject
-import com.google.common.truth.Truth.assertThat
-import com.google.common.truth.Truth.assertWithMessage
-import kotlinx.coroutines.runBlocking
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.util.concurrent.CountDownLatch
-
-@LargeTest
-@RunWith(AndroidJUnit4::class)
-class LazyColumnForTest {
-    private val LazyColumnForTag = "TestLazyColumnFor"
-
-    @get:Rule
-    val rule = createComposeRule()
-
-    @Test
-    fun compositionsAreDisposed_whenNodesAreScrolledOff() {
-        var composed: Boolean
-        var disposed = false
-        // Ten 31dp spacers in a 300dp list
-        val latch = CountDownLatch(10)
-        // Make it long enough that it's _definitely_ taller than the screen
-        val data = (1..50).toList()
-
-        rule.setContent {
-            // Fixed height to eliminate device size as a factor
-            Box(Modifier.testTag(LazyColumnForTag).preferredHeight(300.dp)) {
-                LazyColumnFor(items = data, modifier = Modifier.fillMaxSize()) {
-                    onCommit {
-                        composed = true
-                        // Signal when everything is done composing
-                        latch.countDown()
-                        onDispose {
-                            disposed = true
-                        }
-                    }
-
-                    // There will be 10 of these in the 300dp box
-                    Spacer(Modifier.preferredHeight(31.dp))
-                }
-            }
-        }
-
-        latch.await()
-        composed = false
-
-        assertWithMessage("Compositions were disposed before we did any scrolling")
-            .that(disposed).isFalse()
-
-        // Mostly a validity check, this is not part of the behavior under test
-        assertWithMessage("Additional composition occurred for no apparent reason")
-            .that(composed).isFalse()
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .performGesture { swipeUp() }
-
-        rule.waitForIdle()
-
-        assertWithMessage("No additional items were composed after scroll, scroll didn't work")
-            .that(composed).isTrue()
-
-        // We may need to modify this test once we prefetch/cache items outside the viewport
-        assertWithMessage(
-            "No compositions were disposed after scrolling, compositions were leaked"
-        ).that(disposed).isTrue()
-    }
-
-    @Test
-    fun compositionsAreDisposed_whenDataIsChanged() {
-        var composed = 0
-        var disposals = 0
-        val data1 = (1..3).toList()
-        val data2 = (4..5).toList() // smaller, to ensure removal is handled properly
-
-        var part2 by mutableStateOf(false)
-
-        rule.setContent {
-            LazyColumnFor(
-                items = if (!part2) data1 else data2,
-                modifier = Modifier.testTag(LazyColumnForTag).fillMaxSize()
-            ) {
-                onCommit {
-                    composed++
-                    onDispose {
-                        disposals++
-                    }
-                }
-
-                Spacer(Modifier.height(50.dp))
-            }
-        }
-
-        rule.runOnIdle {
-            assertWithMessage("Not all items were composed")
-                .that(composed).isEqualTo(data1.size)
-            composed = 0
-
-            part2 = true
-        }
-
-        rule.runOnIdle {
-            assertWithMessage(
-                "No additional items were composed after data change, something didn't work"
-            ).that(composed).isEqualTo(data2.size)
-
-            // We may need to modify this test once we prefetch/cache items outside the viewport
-            assertWithMessage(
-                "Not enough compositions were disposed after scrolling, compositions were leaked"
-            ).that(disposals).isEqualTo(data1.size)
-        }
-    }
-
-    @Test
-    fun compositionsAreDisposed_whenAdapterListIsDisposed() {
-        var emitAdapterList by mutableStateOf(true)
-        var disposeCalledOnFirstItem = false
-        var disposeCalledOnSecondItem = false
-
-        rule.setContent {
-            if (emitAdapterList) {
-                LazyColumnFor(
-                    items = listOf(0, 1),
-                    modifier = Modifier.fillMaxSize()
-                ) {
-                    Box(Modifier.size(100.dp))
-                    onDispose {
-                        if (it == 1) {
-                            disposeCalledOnFirstItem = true
-                        } else {
-                            disposeCalledOnSecondItem = true
-                        }
-                    }
-                }
-            }
-        }
-
-        rule.runOnIdle {
-            assertWithMessage("First item is not immediately disposed")
-                .that(disposeCalledOnFirstItem).isFalse()
-            assertWithMessage("Second item is not immediately disposed")
-                .that(disposeCalledOnFirstItem).isFalse()
-            emitAdapterList = false
-        }
-
-        rule.runOnIdle {
-            assertWithMessage("First item is correctly disposed")
-                .that(disposeCalledOnFirstItem).isTrue()
-            assertWithMessage("Second item is correctly disposed")
-                .that(disposeCalledOnSecondItem).isTrue()
-        }
-    }
-
-    @Test
-    fun removeItemsTest() {
-        val startingNumItems = 3
-        var numItems = startingNumItems
-        var numItemsModel by mutableStateOf(numItems)
-        val tag = "List"
-        rule.setContent {
-            LazyColumnFor((1..numItemsModel).toList(), modifier = Modifier.testTag(tag)) {
-                BasicText("$it")
-            }
-        }
-
-        while (numItems >= 0) {
-            // Confirm the number of children to ensure there are no extra items
-            rule.onNodeWithTag(tag)
-                .onChildren()
-                .assertCountEquals(numItems)
-
-            // Confirm the children's content
-            for (i in 1..3) {
-                rule.onNodeWithText("$i").apply {
-                    if (i <= numItems) {
-                        assertExists()
-                    } else {
-                        assertDoesNotExist()
-                    }
-                }
-            }
-            numItems--
-            if (numItems >= 0) {
-                // Don't set the model to -1
-                rule.runOnIdle { numItemsModel = numItems }
-            }
-        }
-    }
-
-    @Test
-    fun changingDataTest() {
-        val dataLists = listOf(
-            (1..3).toList(),
-            (4..8).toList(),
-            (3..4).toList()
-        )
-        var dataModel by mutableStateOf(dataLists[0])
-        val tag = "List"
-        rule.setContent {
-            LazyColumnFor(dataModel, modifier = Modifier.testTag(tag)) {
-                BasicText("$it")
-            }
-        }
-
-        for (data in dataLists) {
-            rule.runOnIdle { dataModel = data }
-
-            // Confirm the number of children to ensure there are no extra items
-            val numItems = data.size
-            rule.onNodeWithTag(tag)
-                .onChildren()
-                .assertCountEquals(numItems)
-
-            // Confirm the children's content
-            for (item in data) {
-                rule.onNodeWithText("$item").assertExists()
-            }
-        }
-    }
-
-    @Test
-    fun whenItemsAreInitiallyCreatedWith0SizeWeCanScrollWhenTheyExpanded() {
-        val thirdTag = "third"
-        val items = (1..3).toList()
-        var thirdHasSize by mutableStateOf(false)
-
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.fillMaxWidth()
-                    .preferredHeight(100.dp)
-                    .testTag(LazyColumnForTag)
-            ) {
-                if (it == 3) {
-                    Spacer(
-                        Modifier.testTag(thirdTag)
-                            .fillParentMaxWidth()
-                            .preferredHeight(if (thirdHasSize) 60.dp else 0.dp)
-                    )
-                } else {
-                    Spacer(Modifier.fillParentMaxWidth().preferredHeight(60.dp))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 21.dp, density = rule.density)
-
-        rule.onNodeWithTag(thirdTag)
-            .assertExists()
-            .assertIsNotDisplayed()
-
-        rule.runOnIdle {
-            thirdHasSize = true
-        }
-
-        rule.waitForIdle()
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 10.dp, density = rule.density)
-
-        rule.onNodeWithTag(thirdTag)
-            .assertIsDisplayed()
-    }
-
-    @Test
-    fun lazyColumnWrapsContent() = with(rule.density) {
-        val itemInsideLazyColumn = "itemInsideLazyColumn"
-        val itemOutsideLazyColumn = "itemOutsideLazyColumn"
-        var sameSizeItems by mutableStateOf(true)
-
-        rule.setContent {
-            Row {
-                LazyColumnFor(
-                    items = listOf(1, 2),
-                    modifier = Modifier.testTag(LazyColumnForTag)
-                ) {
-                    if (it == 1) {
-                        Spacer(Modifier.preferredSize(50.dp).testTag(itemInsideLazyColumn))
-                    } else {
-                        Spacer(Modifier.preferredSize(if (sameSizeItems) 50.dp else 70.dp))
-                    }
-                }
-                Spacer(Modifier.preferredSize(50.dp).testTag(itemOutsideLazyColumn))
-            }
-        }
-
-        rule.onNodeWithTag(itemInsideLazyColumn)
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag(itemOutsideLazyColumn)
-            .assertIsDisplayed()
-
-        var lazyColumnBounds = rule.onNodeWithTag(LazyColumnForTag)
-            .getUnclippedBoundsInRoot()
-
-        assertThat(lazyColumnBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-        assertThat(lazyColumnBounds.right.toIntPx()).isWithin1PixelFrom(50.dp.toIntPx())
-        assertThat(lazyColumnBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-        assertThat(lazyColumnBounds.bottom.toIntPx()).isWithin1PixelFrom(100.dp.toIntPx())
-
-        rule.runOnIdle {
-            sameSizeItems = false
-        }
-
-        rule.waitForIdle()
-
-        rule.onNodeWithTag(itemInsideLazyColumn)
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag(itemOutsideLazyColumn)
-            .assertIsDisplayed()
-
-        lazyColumnBounds = rule.onNodeWithTag(LazyColumnForTag)
-            .getUnclippedBoundsInRoot()
-
-        assertThat(lazyColumnBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-        assertThat(lazyColumnBounds.right.toIntPx()).isWithin1PixelFrom(70.dp.toIntPx())
-        assertThat(lazyColumnBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-        assertThat(lazyColumnBounds.bottom.toIntPx()).isWithin1PixelFrom(120.dp.toIntPx())
-    }
-
-    private val firstItemTag = "firstItemTag"
-    private val secondItemTag = "secondItemTag"
-
-    private fun prepareLazyColumnsItemsAlignment(horizontalGravity: Alignment.Horizontal) {
-        rule.setContent {
-            LazyColumnFor(
-                items = listOf(1, 2),
-                modifier = Modifier.testTag(LazyColumnForTag).width(100.dp),
-                horizontalAlignment = horizontalGravity
-            ) {
-                if (it == 1) {
-                    Spacer(Modifier.preferredSize(50.dp).testTag(firstItemTag))
-                } else {
-                    Spacer(Modifier.preferredSize(70.dp).testTag(secondItemTag))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag(secondItemTag)
-            .assertIsDisplayed()
-
-        val lazyColumnBounds = rule.onNodeWithTag(LazyColumnForTag)
-            .getUnclippedBoundsInRoot()
-
-        with(rule.density) {
-            // Verify the width of the column
-            assertThat(lazyColumnBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-            assertThat(lazyColumnBounds.right.toIntPx()).isWithin1PixelFrom(100.dp.toIntPx())
-        }
-    }
-
-    @Test
-    fun lazyColumnAlignmentCenterHorizontally() {
-        prepareLazyColumnsItemsAlignment(Alignment.CenterHorizontally)
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertPositionInRootIsEqualTo(25.dp, 0.dp)
-
-        rule.onNodeWithTag(secondItemTag)
-            .assertPositionInRootIsEqualTo(15.dp, 50.dp)
-    }
-
-    @Test
-    fun lazyColumnAlignmentStart() {
-        prepareLazyColumnsItemsAlignment(Alignment.Start)
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertPositionInRootIsEqualTo(0.dp, 0.dp)
-
-        rule.onNodeWithTag(secondItemTag)
-            .assertPositionInRootIsEqualTo(0.dp, 50.dp)
-    }
-
-    @Test
-    fun lazyColumnAlignmentEnd() {
-        prepareLazyColumnsItemsAlignment(Alignment.End)
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertPositionInRootIsEqualTo(50.dp, 0.dp)
-
-        rule.onNodeWithTag(secondItemTag)
-            .assertPositionInRootIsEqualTo(30.dp, 50.dp)
-    }
-
-    @Test
-    fun itemFillingParentWidth() {
-        rule.setContent {
-            LazyColumnFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.fillParentMaxWidth().height(50.dp).testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(100.dp)
-            .assertHeightIsEqualTo(50.dp)
-    }
-
-    @Test
-    fun itemFillingParentHeight() {
-        rule.setContent {
-            LazyColumnFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.width(50.dp).fillParentMaxHeight().testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(50.dp)
-            .assertHeightIsEqualTo(150.dp)
-    }
-
-    @Test
-    fun itemFillingParentSize() {
-        rule.setContent {
-            LazyColumnFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(100.dp)
-            .assertHeightIsEqualTo(150.dp)
-    }
-
-    @Test
-    fun itemFillingParentWidthFraction() {
-        rule.setContent {
-            LazyColumnFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.fillParentMaxWidth(0.6f).height(50.dp).testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(60.dp)
-            .assertHeightIsEqualTo(50.dp)
-    }
-
-    @Test
-    fun itemFillingParentHeightFraction() {
-        rule.setContent {
-            LazyColumnFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.width(50.dp).fillParentMaxHeight(0.2f).testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(50.dp)
-            .assertHeightIsEqualTo(30.dp)
-    }
-
-    @Test
-    fun itemFillingParentSizeFraction() {
-        rule.setContent {
-            LazyColumnFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.fillParentMaxSize(0.1f).testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(10.dp)
-            .assertHeightIsEqualTo(15.dp)
-    }
-
-    @Test
-    fun itemFillingParentSizeParentResized() {
-        var parentSize by mutableStateOf(100.dp)
-        rule.setContent {
-            LazyColumnFor(
-                items = listOf(0),
-                modifier = Modifier.size(parentSize)
-            ) {
-                Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
-            }
-        }
-
-        rule.runOnIdle {
-            parentSize = 150.dp
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(150.dp)
-            .assertHeightIsEqualTo(150.dp)
-    }
-
-    @Test
-    fun whenNotAnymoreAvailableItemWasDisplayed() {
-        var items by mutableStateOf((1..30).toList())
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // after scroll we will display items 16-20
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 300.dp, density = rule.density)
-
-        rule.runOnIdle {
-            items = (1..10).toList()
-        }
-
-        // there is no item 16 anymore so we will just display the last items 6-10
-        rule.onNodeWithTag("6")
-            .assertTopPositionIsAlmost(0.dp)
-    }
-
-    @Test
-    fun whenFewDisplayedItemsWereRemoved() {
-        var items by mutableStateOf((1..10).toList())
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // after scroll we will display items 6-10
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 100.dp, density = rule.density)
-
-        rule.runOnIdle {
-            items = (1..8).toList()
-        }
-
-        // there are no more items 9 and 10, so we have to scroll back
-        rule.onNodeWithTag("4")
-            .assertTopPositionIsAlmost(0.dp)
-    }
-
-    @Test
-    fun whenItemsBecameEmpty() {
-        var items by mutableStateOf((1..10).toList())
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.sizeIn(maxHeight = 100.dp).testTag(LazyColumnForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // after scroll we will display items 2-6
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 20.dp, density = rule.density)
-
-        rule.runOnIdle {
-            items = emptyList()
-        }
-
-        // there are no more items so the LazyColumn is zero sized
-        rule.onNodeWithTag(LazyColumnForTag)
-            .assertWidthIsEqualTo(0.dp)
-            .assertHeightIsEqualTo(0.dp)
-
-        // and has no children
-        rule.onNodeWithTag("1")
-            .assertDoesNotExist()
-        rule.onNodeWithTag("2")
-            .assertDoesNotExist()
-    }
-
-    @Test
-    fun scrollBackAndForth() {
-        val items by mutableStateOf((1..20).toList())
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // after scroll we will display items 6-10
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 100.dp, density = rule.density)
-
-        // and scroll back
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = (-100).dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertTopPositionIsAlmost(0.dp)
-    }
-
-    @Test
-    fun tryToScrollBackwardWhenAlreadyOnTop() {
-        val items by mutableStateOf((1..20).toList())
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // we already displaying the first item, so this should do nothing
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = (-50).dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertTopPositionIsAlmost(0.dp)
-        rule.onNodeWithTag("5")
-            .assertTopPositionIsAlmost(80.dp)
-    }
-
-    @Test
-    fun contentOfNotStableItemsIsNotRecomposedDuringScroll() {
-        val items = listOf(NotStable(1), NotStable(2))
-        var firstItemRecomposed = 0
-        var secondItemRecomposed = 0
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag)
-            ) {
-                if (it.count == 1) {
-                    firstItemRecomposed++
-                } else {
-                    secondItemRecomposed++
-                }
-                Spacer(Modifier.size(75.dp))
-            }
-        }
-
-        rule.runOnIdle {
-            assertThat(firstItemRecomposed).isEqualTo(1)
-            assertThat(secondItemRecomposed).isEqualTo(1)
-        }
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = (50).dp, density = rule.density)
-
-        rule.runOnIdle {
-            assertThat(firstItemRecomposed).isEqualTo(1)
-            assertThat(secondItemRecomposed).isEqualTo(1)
-        }
-    }
-
-    @Test
-    fun onlyOneMeasurePassForScrollEvent() {
-        val items by mutableStateOf((1..20).toList())
-        lateinit var state: LazyListState
-        rule.setContent {
-            state = rememberLazyListState()
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        val initialMeasurePasses = state.numMeasurePasses
-
-        rule.runOnIdle {
-            with(rule.density) {
-                state.onScroll(-110.dp.toPx())
-            }
-        }
-
-        rule.waitForIdle()
-
-        assertThat(state.numMeasurePasses).isEqualTo(initialMeasurePasses + 1)
-    }
-
-    @Test
-    fun stateUpdatedAfterScroll() {
-        val items by mutableStateOf((1..20).toList())
-        lateinit var state: LazyListState
-        rule.setContent {
-            state = rememberLazyListState()
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.runOnIdle {
-            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
-            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
-        }
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 30.dp, density = rule.density)
-
-        rule.runOnIdle {
-            assertThat(state.firstVisibleItemIndex).isEqualTo(1)
-
-            with(rule.density) {
-                // TODO(b/169232491): test scrolling doesn't appear to be scrolling exactly the right
-                //  number of pixels
-                val expectedOffset = 10.dp.toIntPx()
-                val tolerance = 2.dp.toIntPx()
-                assertThat(state.firstVisibleItemScrollOffset).isEqualTo(expectedOffset, tolerance)
-            }
-        }
-    }
-
-    @Test
-    fun isAnimationRunningUpdate() {
-        val items by mutableStateOf((1..20).toList())
-        val clock = ManualAnimationClock(0L)
-        val state = LazyListState(
-            flingConfig = FlingConfig(ExponentialDecay()),
-            animationClock = clock
-        )
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.runOnIdle {
-            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
-            assertThat(state.isAnimationRunning).isEqualTo(false)
-        }
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .performGesture { swipeUp() }
-
-        rule.runOnIdle {
-            clock.clockTimeMillis += 100
-            assertThat(state.firstVisibleItemIndex).isNotEqualTo(0)
-            assertThat(state.isAnimationRunning).isEqualTo(true)
-        }
-
-        // TODO (jelle): this should be down, and not click to be 100% fair
-        rule.onNodeWithTag(LazyColumnForTag)
-            .performGesture { click() }
-
-        rule.runOnIdle {
-            assertThat(state.isAnimationRunning).isEqualTo(false)
-        }
-    }
-
-    @Test
-    fun stateUpdatedAfterScrollWithinTheSameItem() {
-        val items by mutableStateOf((1..20).toList())
-        lateinit var state: LazyListState
-        rule.setContent {
-            state = rememberLazyListState()
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 10.dp, density = rule.density)
-
-        rule.runOnIdle {
-            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
-            with(rule.density) {
-                val expectedOffset = 10.dp.toIntPx()
-                val tolerance = 2.dp.toIntPx()
-                assertThat(state.firstVisibleItemScrollOffset)
-                    .isEqualTo(expectedOffset, tolerance)
-            }
-        }
-    }
-
-    @Test
-    fun initialScrollIsApplied() {
-        val items by mutableStateOf((0..20).toList())
-        lateinit var state: LazyListState
-        val expectedOffset = with(rule.density) { 10.dp.toIntPx() }
-        rule.setContent {
-            state = rememberLazyListState(2, expectedOffset)
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.runOnIdle {
-            assertThat(state.firstVisibleItemIndex).isEqualTo(2)
-            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(expectedOffset)
-        }
-
-        rule.onNodeWithTag("2")
-            .assertTopPositionInRootIsEqualTo((-10).dp)
-    }
-
-    @Test
-    fun stateIsRestored() {
-        val restorationTester = StateRestorationTester(rule)
-        val items by mutableStateOf((1..20).toList())
-        var state: LazyListState? = null
-        restorationTester.setContent {
-            state = rememberLazyListState()
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag),
-                state = state!!
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 30.dp, density = rule.density)
-
-        val (index, scrollOffset) = rule.runOnIdle {
-            state!!.firstVisibleItemIndex to state!!.firstVisibleItemScrollOffset
-        }
-
-        state = null
-
-        restorationTester.emulateSavedInstanceStateRestore()
-
-        rule.runOnIdle {
-            assertThat(state!!.firstVisibleItemIndex).isEqualTo(index)
-            assertThat(state!!.firstVisibleItemScrollOffset).isEqualTo(scrollOffset)
-        }
-    }
-
-    @Test
-    fun scroll_makeListSmaller_scroll() {
-        var items by mutableStateOf((1..100).toList())
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag)
-            ) {
-                Spacer(Modifier.size(10.dp).testTag("$it"))
-            }
-        }
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 300.dp, density = rule.density)
-
-        rule.runOnIdle {
-            items = (1..11).toList()
-        }
-
-        // try to scroll after the data set has been updated. this was causing a crash previously
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = (-10).dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertIsDisplayed()
-    }
-
-    @Test
-    fun snapToItemIndex() {
-        val items by mutableStateOf((1..20).toList())
-        lateinit var state: LazyListState
-        rule.setContent {
-            state = rememberLazyListState()
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.runOnIdle {
-            runBlocking {
-                state.snapToItemIndex(3, 10)
-            }
-            assertThat(state.firstVisibleItemIndex).isEqualTo(3)
-            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(10)
-        }
-    }
-
-    @Test
-    fun itemsAreNotRedrawnDuringScroll() {
-        val items = (0..20).toList()
-        val redrawCount = Array(6) { 0 }
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag)
-            ) {
-                Spacer(
-                    Modifier.size(20.dp)
-                        .drawBehind { redrawCount[it]++ }
-                )
-            }
-        }
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .scrollBy(y = 10.dp, density = rule.density)
-
-        rule.runOnIdle {
-            redrawCount.forEachIndexed { index, i ->
-                assertWithMessage("Item with index $index was redrawn $i times")
-                    .that(i).isEqualTo(1)
-            }
-        }
-    }
-
-    @Test
-    fun itemInvalidationIsNotCausingAnotherItemToRedraw() {
-        val items = (0..1).toList()
-        val redrawCount = Array(2) { 0 }
-        var stateUsedInDrawScope by mutableStateOf(false)
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyColumnForTag)
-            ) {
-                Spacer(
-                    Modifier.size(50.dp)
-                        .drawBehind {
-                            redrawCount[it]++
-                            if (it == 1) {
-                                stateUsedInDrawScope.hashCode()
-                            }
-                        }
-                )
-            }
-        }
-
-        rule.runOnIdle {
-            stateUsedInDrawScope = true
-        }
-
-        rule.runOnIdle {
-            assertWithMessage("First items is not expected to be redrawn")
-                .that(redrawCount[0]).isEqualTo(1)
-            assertWithMessage("Second items is expected to be redrawn")
-                .that(redrawCount[1]).isEqualTo(2)
-        }
-    }
-
-    @Test
-    fun notVisibleAnymoreItemNotAffectingCrossAxisSize() {
-        val items = (0..1).toList()
-        val itemSize = with(rule.density) { 30.toDp() }
-        val itemSizeMinusOne = with(rule.density) { 29.toDp() }
-        lateinit var state: LazyListState
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                state = rememberLazyListState().also { state = it },
-                modifier = Modifier.height(itemSizeMinusOne).testTag(LazyColumnForTag)
-            ) {
-                Spacer(
-                    if (it == 0) {
-                        Modifier.width(30.dp).height(itemSizeMinusOne)
-                    } else {
-                        Modifier.width(20.dp).height(itemSize)
-                    }
-                )
-            }
-        }
-
-        state.scrollBy(itemSize)
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .assertWidthIsEqualTo(20.dp)
-    }
-
-    @Test
-    fun itemStillVisibleAfterOverscrollIsAffectingCrossAxisSize() {
-        val items = (0..2).toList()
-        val itemSize = with(rule.density) { 30.toDp() }
-        lateinit var state: LazyListState
-        rule.setContent {
-            LazyColumnFor(
-                items = items,
-                state = rememberLazyListState().also { state = it },
-                modifier = Modifier.height(itemSize * 1.75f).testTag(LazyColumnForTag)
-            ) {
-                Spacer(
-                    if (it == 0) {
-                        Modifier.width(30.dp).height(itemSize / 2)
-                    } else if (it == 1) {
-                        Modifier.width(20.dp).height(itemSize / 2)
-                    } else {
-                        Modifier.width(20.dp).height(itemSize)
-                    }
-                )
-            }
-        }
-
-        state.scrollBy(itemSize)
-
-        rule.onNodeWithTag(LazyColumnForTag)
-            .assertWidthIsEqualTo(30.dp)
-    }
-
-    private fun SemanticsNodeInteraction.assertTopPositionIsAlmost(expected: Dp) {
-        getUnclippedBoundsInRoot().top.assertIsEqualTo(expected, tolerance = 1.dp)
-    }
-
-    private fun LazyListState.scrollBy(offset: Dp) {
-        runBlocking {
-            smoothScrollBy(with(rule.density) { offset.toIntPx().toFloat() }, snap())
-        }
-    }
-}
-
-data class NotStable(val count: Int)
-
-internal fun IntegerSubject.isWithin1PixelFrom(expected: Int) {
-    isEqualTo(expected, 1)
-}
-
-internal fun IntegerSubject.isEqualTo(expected: Int, tolerance: Int) {
-    isIn(Range.closed(expected - tolerance, expected + tolerance))
-}
-
-internal fun SemanticsNodeInteraction.scrollBy(x: Dp = 0.dp, y: Dp = 0.dp, density: Density) =
-    performGesture {
-        with(density) {
-            val touchSlop = TouchSlop.toIntPx()
-            val xPx = x.toIntPx()
-            val yPx = y.toIntPx()
-            val offsetX = if (xPx > 0) xPx + touchSlop else if (xPx < 0) xPx - touchSlop else 0
-            val offsetY = if (yPx > 0) yPx + touchSlop else if (yPx < 0) yPx - touchSlop else 0
-            swipeWithVelocity(
-                start = center,
-                end = Offset(center.x - offsetX, center.y - offsetY),
-                endVelocity = 0f
-            )
-        }
-    }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
index 7e629eb3..d0c6400 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
@@ -16,101 +16,77 @@
 
 package androidx.compose.foundation.lazy
 
+import androidx.compose.animation.core.ExponentialDecay
+import androidx.compose.animation.core.ManualAnimationClock
+import androidx.compose.animation.core.snap
+import androidx.compose.foundation.animation.FlingConfig
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.preferredHeight
 import androidx.compose.foundation.layout.preferredSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.sizeIn
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.onCommit
+import androidx.compose.runtime.onDispose
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.gesture.TouchSlop
 import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.assertCountEquals
+import androidx.compose.ui.test.assertHeightIsEqualTo
 import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertIsEqualTo
+import androidx.compose.ui.test.assertIsNotDisplayed
+import androidx.compose.ui.test.assertPositionInRootIsEqualTo
+import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
+import androidx.compose.ui.test.assertWidthIsEqualTo
+import androidx.compose.ui.test.center
+import androidx.compose.ui.test.click
+import androidx.compose.ui.test.getUnclippedBoundsInRoot
+import androidx.compose.ui.test.junit4.StateRestorationTester
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onChildren
 import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performGesture
+import androidx.compose.ui.test.swipeUp
+import androidx.compose.ui.test.swipeWithVelocity
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.MediumTest
+import androidx.test.filters.LargeTest
+import com.google.common.collect.Range
+import com.google.common.truth.IntegerSubject
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.runBlocking
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import java.util.concurrent.CountDownLatch
 
-@MediumTest
+@LargeTest
 @RunWith(AndroidJUnit4::class)
 class LazyColumnTest {
-    private val LazyColumnTag = "LazyColumnTag"
+    private val LazyListTag = "LazyListTag"
 
     @get:Rule
     val rule = createComposeRule()
 
     @Test
-    fun lazyColumnShowsItem() {
-        val itemTestTag = "itemTestTag"
-
-        rule.setContent {
-            LazyColumn {
-                item {
-                    Spacer(
-                        Modifier.preferredHeight(10.dp).fillParentMaxWidth().testTag(itemTestTag)
-                    )
-                }
-            }
-        }
-
-        rule.onNodeWithTag(itemTestTag)
-            .assertIsDisplayed()
-    }
-
-    @Test
-    fun lazyColumnShowsItems() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            LazyColumn(Modifier.preferredHeight(200.dp)) {
-                items(items) {
-                    Spacer(Modifier.preferredHeight(101.dp).fillParentMaxWidth().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag("1")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("4")
-            .assertDoesNotExist()
-    }
-
-    @Test
-    fun lazyColumnShowsIndexedItems() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            LazyColumn(Modifier.preferredHeight(200.dp)) {
-                itemsIndexed(items) { index, item ->
-                    Spacer(
-                        Modifier.preferredHeight(101.dp).fillParentMaxWidth()
-                            .testTag("$index-$item")
-                    )
-                }
-            }
-        }
-
-        rule.onNodeWithTag("0-1")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("1-2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("2-3")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("3-4")
-            .assertDoesNotExist()
-    }
-
-    @Test
     fun lazyColumnShowsCombinedItems() {
         val itemTestTag = "itemTestTag"
         val items = listOf(1, 2).map { it.toString() }
@@ -155,59 +131,6 @@
     }
 
     @Test
-    fun lazyColumnShowsItemsOnScroll() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            LazyColumn(Modifier.preferredHeight(200.dp).testTag(LazyColumnTag)) {
-                items(items) {
-                    Spacer(Modifier.preferredHeight(101.dp).fillParentMaxWidth().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(LazyColumnTag)
-            .scrollBy(y = 50.dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("4")
-            .assertDoesNotExist()
-    }
-
-    @Test
-    fun lazyColumnScrollHidesItem() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            LazyColumn(Modifier.preferredHeight(200.dp).testTag(LazyColumnTag)) {
-                items(items) {
-                    Spacer(Modifier.preferredHeight(101.dp).fillParentMaxWidth().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(LazyColumnTag)
-            .scrollBy(y = 103.dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertIsDisplayed()
-    }
-
-    @Test
     fun lazyColumnAllowEmptyListItems() {
         val itemTag = "itemTag"
 
@@ -253,4 +176,1050 @@
         rule.onNodeWithTag("3")
             .assertDoesNotExist()
     }
-}
\ No newline at end of file
+
+    @Test
+    fun compositionsAreDisposed_whenNodesAreScrolledOff() {
+        var composed: Boolean
+        var disposed = false
+        // Ten 31dp spacers in a 300dp list
+        val latch = CountDownLatch(10)
+        // Make it long enough that it's _definitely_ taller than the screen
+        val data = (1..50).toList()
+
+        rule.setContent {
+            // Fixed height to eliminate device size as a factor
+            Box(Modifier.testTag(LazyListTag).preferredHeight(300.dp)) {
+                LazyColumn(Modifier.fillMaxSize()) {
+                    items(data) {
+                        onCommit {
+                            composed = true
+                            // Signal when everything is done composing
+                            latch.countDown()
+                            onDispose {
+                                disposed = true
+                            }
+                        }
+
+                        // There will be 10 of these in the 300dp box
+                        Spacer(Modifier.preferredHeight(31.dp))
+                    }
+                }
+            }
+        }
+
+        latch.await()
+        composed = false
+
+        assertWithMessage("Compositions were disposed before we did any scrolling")
+            .that(disposed).isFalse()
+
+        // Mostly a validity check, this is not part of the behavior under test
+        assertWithMessage("Additional composition occurred for no apparent reason")
+            .that(composed).isFalse()
+
+        rule.onNodeWithTag(LazyListTag)
+            .performGesture { swipeUp() }
+
+        rule.waitForIdle()
+
+        assertWithMessage("No additional items were composed after scroll, scroll didn't work")
+            .that(composed).isTrue()
+
+        // We may need to modify this test once we prefetch/cache items outside the viewport
+        assertWithMessage(
+            "No compositions were disposed after scrolling, compositions were leaked"
+        ).that(disposed).isTrue()
+    }
+
+    @Test
+    fun compositionsAreDisposed_whenDataIsChanged() {
+        var composed = 0
+        var disposals = 0
+        val data1 = (1..3).toList()
+        val data2 = (4..5).toList() // smaller, to ensure removal is handled properly
+
+        var part2 by mutableStateOf(false)
+
+        rule.setContent {
+            LazyColumn(Modifier.testTag(LazyListTag).fillMaxSize()) {
+                items(if (!part2) data1 else data2) {
+                    onCommit {
+                        composed++
+                        onDispose {
+                            disposals++
+                        }
+                    }
+
+                    Spacer(Modifier.height(50.dp))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertWithMessage("Not all items were composed")
+                .that(composed).isEqualTo(data1.size)
+            composed = 0
+
+            part2 = true
+        }
+
+        rule.runOnIdle {
+            assertWithMessage(
+                "No additional items were composed after data change, something didn't work"
+            ).that(composed).isEqualTo(data2.size)
+
+            // We may need to modify this test once we prefetch/cache items outside the viewport
+            assertWithMessage(
+                "Not enough compositions were disposed after scrolling, compositions were leaked"
+            ).that(disposals).isEqualTo(data1.size)
+        }
+    }
+
+    @Test
+    fun compositionsAreDisposed_whenAdapterListIsDisposed() {
+        var emitAdapterList by mutableStateOf(true)
+        var disposeCalledOnFirstItem = false
+        var disposeCalledOnSecondItem = false
+
+        rule.setContent {
+            if (emitAdapterList) {
+                LazyColumn(Modifier.fillMaxSize()) {
+                    items(listOf(0, 1)) {
+                        Box(Modifier.size(100.dp))
+                        onDispose {
+                            if (it == 1) {
+                                disposeCalledOnFirstItem = true
+                            } else {
+                                disposeCalledOnSecondItem = true
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertWithMessage("First item is not immediately disposed")
+                .that(disposeCalledOnFirstItem).isFalse()
+            assertWithMessage("Second item is not immediately disposed")
+                .that(disposeCalledOnFirstItem).isFalse()
+            emitAdapterList = false
+        }
+
+        rule.runOnIdle {
+            assertWithMessage("First item is correctly disposed")
+                .that(disposeCalledOnFirstItem).isTrue()
+            assertWithMessage("Second item is correctly disposed")
+                .that(disposeCalledOnSecondItem).isTrue()
+        }
+    }
+
+    @Test
+    fun removeItemsTest() {
+        val startingNumItems = 3
+        var numItems = startingNumItems
+        var numItemsModel by mutableStateOf(numItems)
+        val tag = "List"
+        rule.setContent {
+            LazyColumn(Modifier.testTag(tag)) {
+                items((1..numItemsModel).toList()) {
+                    BasicText("$it")
+                }
+            }
+        }
+
+        while (numItems >= 0) {
+            // Confirm the number of children to ensure there are no extra items
+            rule.onNodeWithTag(tag)
+                .onChildren()
+                .assertCountEquals(numItems)
+
+            // Confirm the children's content
+            for (i in 1..3) {
+                rule.onNodeWithText("$i").apply {
+                    if (i <= numItems) {
+                        assertExists()
+                    } else {
+                        assertDoesNotExist()
+                    }
+                }
+            }
+            numItems--
+            if (numItems >= 0) {
+                // Don't set the model to -1
+                rule.runOnIdle { numItemsModel = numItems }
+            }
+        }
+    }
+
+    @Test
+    fun changingDataTest() {
+        val dataLists = listOf(
+            (1..3).toList(),
+            (4..8).toList(),
+            (3..4).toList()
+        )
+        var dataModel by mutableStateOf(dataLists[0])
+        val tag = "List"
+        rule.setContent {
+            LazyColumn(Modifier.testTag(tag)) {
+                items(dataModel) {
+                    BasicText("$it")
+                }
+            }
+        }
+
+        for (data in dataLists) {
+            rule.runOnIdle { dataModel = data }
+
+            // Confirm the number of children to ensure there are no extra items
+            val numItems = data.size
+            rule.onNodeWithTag(tag)
+                .onChildren()
+                .assertCountEquals(numItems)
+
+            // Confirm the children's content
+            for (item in data) {
+                rule.onNodeWithText("$item").assertExists()
+            }
+        }
+    }
+
+    @Test
+    fun whenItemsAreInitiallyCreatedWith0SizeWeCanScrollWhenTheyExpanded() {
+        val thirdTag = "third"
+        val items = (1..3).toList()
+        var thirdHasSize by mutableStateOf(false)
+
+        rule.setContent {
+            LazyColumn(
+                Modifier.fillMaxWidth()
+                    .preferredHeight(100.dp)
+                    .testTag(LazyListTag)
+            ) {
+                items(items) {
+                    if (it == 3) {
+                        Spacer(
+                            Modifier.testTag(thirdTag)
+                                .fillParentMaxWidth()
+                                .preferredHeight(if (thirdHasSize) 60.dp else 0.dp)
+                        )
+                    } else {
+                        Spacer(Modifier.fillParentMaxWidth().preferredHeight(60.dp))
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 21.dp, density = rule.density)
+
+        rule.onNodeWithTag(thirdTag)
+            .assertExists()
+            .assertIsNotDisplayed()
+
+        rule.runOnIdle {
+            thirdHasSize = true
+        }
+
+        rule.waitForIdle()
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 10.dp, density = rule.density)
+
+        rule.onNodeWithTag(thirdTag)
+            .assertIsDisplayed()
+    }
+
+    @Test
+    fun lazyColumnWrapsContent() = with(rule.density) {
+        val itemInsideLazyColumn = "itemInsideLazyColumn"
+        val itemOutsideLazyColumn = "itemOutsideLazyColumn"
+        var sameSizeItems by mutableStateOf(true)
+
+        rule.setContent {
+            Row {
+                LazyColumn(Modifier.testTag(LazyListTag)) {
+                    items(listOf(1, 2)) {
+                        if (it == 1) {
+                            Spacer(Modifier.preferredSize(50.dp).testTag(itemInsideLazyColumn))
+                        } else {
+                            Spacer(Modifier.preferredSize(if (sameSizeItems) 50.dp else 70.dp))
+                        }
+                    }
+                }
+                Spacer(Modifier.preferredSize(50.dp).testTag(itemOutsideLazyColumn))
+            }
+        }
+
+        rule.onNodeWithTag(itemInsideLazyColumn)
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag(itemOutsideLazyColumn)
+            .assertIsDisplayed()
+
+        var lazyColumnBounds = rule.onNodeWithTag(LazyListTag)
+            .getUnclippedBoundsInRoot()
+
+        assertThat(lazyColumnBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+        assertThat(lazyColumnBounds.right.toIntPx()).isWithin1PixelFrom(50.dp.toIntPx())
+        assertThat(lazyColumnBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+        assertThat(lazyColumnBounds.bottom.toIntPx()).isWithin1PixelFrom(100.dp.toIntPx())
+
+        rule.runOnIdle {
+            sameSizeItems = false
+        }
+
+        rule.waitForIdle()
+
+        rule.onNodeWithTag(itemInsideLazyColumn)
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag(itemOutsideLazyColumn)
+            .assertIsDisplayed()
+
+        lazyColumnBounds = rule.onNodeWithTag(LazyListTag)
+            .getUnclippedBoundsInRoot()
+
+        assertThat(lazyColumnBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+        assertThat(lazyColumnBounds.right.toIntPx()).isWithin1PixelFrom(70.dp.toIntPx())
+        assertThat(lazyColumnBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+        assertThat(lazyColumnBounds.bottom.toIntPx()).isWithin1PixelFrom(120.dp.toIntPx())
+    }
+
+    private val firstItemTag = "firstItemTag"
+    private val secondItemTag = "secondItemTag"
+
+    private fun prepareLazyColumnsItemsAlignment(horizontalGravity: Alignment.Horizontal) {
+        rule.setContent {
+            LazyColumn(
+                Modifier.testTag(LazyListTag).width(100.dp),
+                horizontalAlignment = horizontalGravity
+            ) {
+                items(listOf(1, 2)) {
+                    if (it == 1) {
+                        Spacer(Modifier.preferredSize(50.dp).testTag(firstItemTag))
+                    } else {
+                        Spacer(Modifier.preferredSize(70.dp).testTag(secondItemTag))
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag(secondItemTag)
+            .assertIsDisplayed()
+
+        val lazyColumnBounds = rule.onNodeWithTag(LazyListTag)
+            .getUnclippedBoundsInRoot()
+
+        with(rule.density) {
+            // Verify the width of the column
+            assertThat(lazyColumnBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+            assertThat(lazyColumnBounds.right.toIntPx()).isWithin1PixelFrom(100.dp.toIntPx())
+        }
+    }
+
+    @Test
+    fun lazyColumnAlignmentCenterHorizontally() {
+        prepareLazyColumnsItemsAlignment(Alignment.CenterHorizontally)
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertPositionInRootIsEqualTo(25.dp, 0.dp)
+
+        rule.onNodeWithTag(secondItemTag)
+            .assertPositionInRootIsEqualTo(15.dp, 50.dp)
+    }
+
+    @Test
+    fun lazyColumnAlignmentStart() {
+        prepareLazyColumnsItemsAlignment(Alignment.Start)
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertPositionInRootIsEqualTo(0.dp, 0.dp)
+
+        rule.onNodeWithTag(secondItemTag)
+            .assertPositionInRootIsEqualTo(0.dp, 50.dp)
+    }
+
+    @Test
+    fun lazyColumnAlignmentEnd() {
+        prepareLazyColumnsItemsAlignment(Alignment.End)
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertPositionInRootIsEqualTo(50.dp, 0.dp)
+
+        rule.onNodeWithTag(secondItemTag)
+            .assertPositionInRootIsEqualTo(30.dp, 50.dp)
+    }
+
+    @Test
+    fun itemFillingParentWidth() {
+        rule.setContent {
+            LazyColumn(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxWidth().height(50.dp).testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(100.dp)
+            .assertHeightIsEqualTo(50.dp)
+    }
+
+    @Test
+    fun itemFillingParentHeight() {
+        rule.setContent {
+            LazyColumn(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.width(50.dp).fillParentMaxHeight().testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(50.dp)
+            .assertHeightIsEqualTo(150.dp)
+    }
+
+    @Test
+    fun itemFillingParentSize() {
+        rule.setContent {
+            LazyColumn(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(100.dp)
+            .assertHeightIsEqualTo(150.dp)
+    }
+
+    @Test
+    fun itemFillingParentWidthFraction() {
+        rule.setContent {
+            LazyColumn(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxWidth(0.6f).height(50.dp).testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(60.dp)
+            .assertHeightIsEqualTo(50.dp)
+    }
+
+    @Test
+    fun itemFillingParentHeightFraction() {
+        rule.setContent {
+            LazyColumn(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.width(50.dp).fillParentMaxHeight(0.2f).testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(50.dp)
+            .assertHeightIsEqualTo(30.dp)
+    }
+
+    @Test
+    fun itemFillingParentSizeFraction() {
+        rule.setContent {
+            LazyColumn(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxSize(0.1f).testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(10.dp)
+            .assertHeightIsEqualTo(15.dp)
+    }
+
+    @Test
+    fun itemFillingParentSizeParentResized() {
+        var parentSize by mutableStateOf(100.dp)
+        rule.setContent {
+            LazyColumn(Modifier.size(parentSize)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            parentSize = 150.dp
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(150.dp)
+            .assertHeightIsEqualTo(150.dp)
+    }
+
+    @Test
+    fun whenNotAnymoreAvailableItemWasDisplayed() {
+        var items by mutableStateOf((1..30).toList())
+        rule.setContent {
+            LazyColumn(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // after scroll we will display items 16-20
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 300.dp, density = rule.density)
+
+        rule.runOnIdle {
+            items = (1..10).toList()
+        }
+
+        // there is no item 16 anymore so we will just display the last items 6-10
+        rule.onNodeWithTag("6")
+            .assertTopPositionIsAlmost(0.dp)
+    }
+
+    @Test
+    fun whenFewDisplayedItemsWereRemoved() {
+        var items by mutableStateOf((1..10).toList())
+        rule.setContent {
+            LazyColumn(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // after scroll we will display items 6-10
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 100.dp, density = rule.density)
+
+        rule.runOnIdle {
+            items = (1..8).toList()
+        }
+
+        // there are no more items 9 and 10, so we have to scroll back
+        rule.onNodeWithTag("4")
+            .assertTopPositionIsAlmost(0.dp)
+    }
+
+    @Test
+    fun whenItemsBecameEmpty() {
+        var items by mutableStateOf((1..10).toList())
+        rule.setContent {
+            LazyColumn(Modifier.sizeIn(maxHeight = 100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // after scroll we will display items 2-6
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 20.dp, density = rule.density)
+
+        rule.runOnIdle {
+            items = emptyList()
+        }
+
+        // there are no more items so the LazyColumn is zero sized
+        rule.onNodeWithTag(LazyListTag)
+            .assertWidthIsEqualTo(0.dp)
+            .assertHeightIsEqualTo(0.dp)
+
+        // and has no children
+        rule.onNodeWithTag("1")
+            .assertDoesNotExist()
+        rule.onNodeWithTag("2")
+            .assertDoesNotExist()
+    }
+
+    @Test
+    fun scrollBackAndForth() {
+        val items by mutableStateOf((1..20).toList())
+        rule.setContent {
+            LazyColumn(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // after scroll we will display items 6-10
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 100.dp, density = rule.density)
+
+        // and scroll back
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = (-100).dp, density = rule.density)
+
+        rule.onNodeWithTag("1")
+            .assertTopPositionIsAlmost(0.dp)
+    }
+
+    @Test
+    fun tryToScrollBackwardWhenAlreadyOnTop() {
+        val items by mutableStateOf((1..20).toList())
+        rule.setContent {
+            LazyColumn(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // we already displaying the first item, so this should do nothing
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = (-50).dp, density = rule.density)
+
+        rule.onNodeWithTag("1")
+            .assertTopPositionIsAlmost(0.dp)
+        rule.onNodeWithTag("5")
+            .assertTopPositionIsAlmost(80.dp)
+    }
+
+    @Test
+    fun contentOfNotStableItemsIsNotRecomposedDuringScroll() {
+        val items = listOf(NotStable(1), NotStable(2))
+        var firstItemRecomposed = 0
+        var secondItemRecomposed = 0
+        rule.setContent {
+            LazyColumn(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    if (it.count == 1) {
+                        firstItemRecomposed++
+                    } else {
+                        secondItemRecomposed++
+                    }
+                    Spacer(Modifier.size(75.dp))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(firstItemRecomposed).isEqualTo(1)
+            assertThat(secondItemRecomposed).isEqualTo(1)
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = (50).dp, density = rule.density)
+
+        rule.runOnIdle {
+            assertThat(firstItemRecomposed).isEqualTo(1)
+            assertThat(secondItemRecomposed).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun onlyOneMeasurePassForScrollEvent() {
+        val items by mutableStateOf((1..20).toList())
+        lateinit var state: LazyListState
+        rule.setContent {
+            state = rememberLazyListState()
+            LazyColumn(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        val initialMeasurePasses = state.numMeasurePasses
+
+        rule.runOnIdle {
+            with(rule.density) {
+                state.onScroll(-110.dp.toPx())
+            }
+        }
+
+        rule.waitForIdle()
+
+        assertThat(state.numMeasurePasses).isEqualTo(initialMeasurePasses + 1)
+    }
+
+    @Test
+    fun stateUpdatedAfterScroll() {
+        val items by mutableStateOf((1..20).toList())
+        lateinit var state: LazyListState
+        rule.setContent {
+            state = rememberLazyListState()
+            LazyColumn(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
+            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 30.dp, density = rule.density)
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(1)
+
+            with(rule.density) {
+                // TODO(b/169232491): test scrolling doesn't appear to be scrolling exactly the right
+                //  number of pixels
+                val expectedOffset = 10.dp.toIntPx()
+                val tolerance = 2.dp.toIntPx()
+                assertThat(state.firstVisibleItemScrollOffset).isEqualTo(expectedOffset, tolerance)
+            }
+        }
+    }
+
+    @Test
+    fun isAnimationRunningUpdate() {
+        val items by mutableStateOf((1..20).toList())
+        val clock = ManualAnimationClock(0L)
+        val state = LazyListState(
+            flingConfig = FlingConfig(ExponentialDecay()),
+            animationClock = clock
+        )
+        rule.setContent {
+            LazyColumn(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
+            assertThat(state.isAnimationRunning).isEqualTo(false)
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .performGesture { swipeUp() }
+
+        rule.runOnIdle {
+            clock.clockTimeMillis += 100
+            assertThat(state.firstVisibleItemIndex).isNotEqualTo(0)
+            assertThat(state.isAnimationRunning).isEqualTo(true)
+        }
+
+        // TODO (jelle): this should be down, and not click to be 100% fair
+        rule.onNodeWithTag(LazyListTag)
+            .performGesture { click() }
+
+        rule.runOnIdle {
+            assertThat(state.isAnimationRunning).isEqualTo(false)
+        }
+    }
+
+    @Test
+    fun stateUpdatedAfterScrollWithinTheSameItem() {
+        val items by mutableStateOf((1..20).toList())
+        lateinit var state: LazyListState
+        rule.setContent {
+            state = rememberLazyListState()
+            LazyColumn(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 10.dp, density = rule.density)
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
+            with(rule.density) {
+                val expectedOffset = 10.dp.toIntPx()
+                val tolerance = 2.dp.toIntPx()
+                assertThat(state.firstVisibleItemScrollOffset)
+                    .isEqualTo(expectedOffset, tolerance)
+            }
+        }
+    }
+
+    @Test
+    fun initialScrollIsApplied() {
+        val items by mutableStateOf((0..20).toList())
+        lateinit var state: LazyListState
+        val expectedOffset = with(rule.density) { 10.dp.toIntPx() }
+        rule.setContent {
+            state = rememberLazyListState(2, expectedOffset)
+            LazyColumn(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(2)
+            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(expectedOffset)
+        }
+
+        rule.onNodeWithTag("2")
+            .assertTopPositionInRootIsEqualTo((-10).dp)
+    }
+
+    @Test
+    fun stateIsRestored() {
+        val restorationTester = StateRestorationTester(rule)
+        val items by mutableStateOf((1..20).toList())
+        var state: LazyListState? = null
+        restorationTester.setContent {
+            state = rememberLazyListState()
+            LazyColumn(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state!!
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 30.dp, density = rule.density)
+
+        val (index, scrollOffset) = rule.runOnIdle {
+            state!!.firstVisibleItemIndex to state!!.firstVisibleItemScrollOffset
+        }
+
+        state = null
+
+        restorationTester.emulateSavedInstanceStateRestore()
+
+        rule.runOnIdle {
+            assertThat(state!!.firstVisibleItemIndex).isEqualTo(index)
+            assertThat(state!!.firstVisibleItemScrollOffset).isEqualTo(scrollOffset)
+        }
+    }
+
+    @Test
+    fun scroll_makeListSmaller_scroll() {
+        var items by mutableStateOf((1..100).toList())
+        rule.setContent {
+            LazyColumn(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(10.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 300.dp, density = rule.density)
+
+        rule.runOnIdle {
+            items = (1..11).toList()
+        }
+
+        // try to scroll after the data set has been updated. this was causing a crash previously
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = (-10).dp, density = rule.density)
+
+        rule.onNodeWithTag("1")
+            .assertIsDisplayed()
+    }
+
+    @Test
+    fun snapToItemIndex() {
+        val items by mutableStateOf((1..20).toList())
+        lateinit var state: LazyListState
+        rule.setContent {
+            state = rememberLazyListState()
+            LazyColumn(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            runBlocking {
+                state.snapToItemIndex(3, 10)
+            }
+            assertThat(state.firstVisibleItemIndex).isEqualTo(3)
+            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(10)
+        }
+    }
+
+    @Test
+    fun itemsAreNotRedrawnDuringScroll() {
+        val items = (0..20).toList()
+        val redrawCount = Array(6) { 0 }
+        rule.setContent {
+            LazyColumn(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(
+                        Modifier.size(20.dp)
+                            .drawBehind { redrawCount[it]++ }
+                    )
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(y = 10.dp, density = rule.density)
+
+        rule.runOnIdle {
+            redrawCount.forEachIndexed { index, i ->
+                assertWithMessage("Item with index $index was redrawn $i times")
+                    .that(i).isEqualTo(1)
+            }
+        }
+    }
+
+    @Test
+    fun itemInvalidationIsNotCausingAnotherItemToRedraw() {
+        val items = (0..1).toList()
+        val redrawCount = Array(2) { 0 }
+        var stateUsedInDrawScope by mutableStateOf(false)
+        rule.setContent {
+            LazyColumn(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(
+                        Modifier.size(50.dp)
+                            .drawBehind {
+                                redrawCount[it]++
+                                if (it == 1) {
+                                    stateUsedInDrawScope.hashCode()
+                                }
+                            }
+                    )
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            stateUsedInDrawScope = true
+        }
+
+        rule.runOnIdle {
+            assertWithMessage("First items is not expected to be redrawn")
+                .that(redrawCount[0]).isEqualTo(1)
+            assertWithMessage("Second items is expected to be redrawn")
+                .that(redrawCount[1]).isEqualTo(2)
+        }
+    }
+
+    @Test
+    fun notVisibleAnymoreItemNotAffectingCrossAxisSize() {
+        val items = (0..1).toList()
+        val itemSize = with(rule.density) { 30.toDp() }
+        val itemSizeMinusOne = with(rule.density) { 29.toDp() }
+        lateinit var state: LazyListState
+        rule.setContent {
+            LazyColumn(
+                Modifier.height(itemSizeMinusOne).testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it }
+            ) {
+                items(items) {
+                    Spacer(
+                        if (it == 0) {
+                            Modifier.width(30.dp).height(itemSizeMinusOne)
+                        } else {
+                            Modifier.width(20.dp).height(itemSize)
+                        }
+                    )
+                }
+            }
+        }
+
+        state.scrollBy(itemSize)
+
+        rule.onNodeWithTag(LazyListTag)
+            .assertWidthIsEqualTo(20.dp)
+    }
+
+    @Test
+    fun itemStillVisibleAfterOverscrollIsAffectingCrossAxisSize() {
+        val items = (0..2).toList()
+        val itemSize = with(rule.density) { 30.toDp() }
+        lateinit var state: LazyListState
+        rule.setContent {
+            LazyColumn(
+                Modifier.height(itemSize * 1.75f).testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it }
+            ) {
+                items(items) {
+                    Spacer(
+                        if (it == 0) {
+                            Modifier.width(30.dp).height(itemSize / 2)
+                        } else if (it == 1) {
+                            Modifier.width(20.dp).height(itemSize / 2)
+                        } else {
+                            Modifier.width(20.dp).height(itemSize)
+                        }
+                    )
+                }
+            }
+        }
+
+        state.scrollBy(itemSize)
+
+        rule.onNodeWithTag(LazyListTag)
+            .assertWidthIsEqualTo(30.dp)
+    }
+
+    private fun SemanticsNodeInteraction.assertTopPositionIsAlmost(expected: Dp) {
+        getUnclippedBoundsInRoot().top.assertIsEqualTo(expected, tolerance = 1.dp)
+    }
+
+    private fun LazyListState.scrollBy(offset: Dp) {
+        runBlocking {
+            smoothScrollBy(with(rule.density) { offset.toIntPx().toFloat() }, snap())
+        }
+    }
+}
+
+data class NotStable(val count: Int)
+
+internal fun IntegerSubject.isWithin1PixelFrom(expected: Int) {
+    isEqualTo(expected, 1)
+}
+
+internal fun IntegerSubject.isEqualTo(expected: Int, tolerance: Int) {
+    isIn(Range.closed(expected - tolerance, expected + tolerance))
+}
+
+internal fun SemanticsNodeInteraction.scrollBy(x: Dp = 0.dp, y: Dp = 0.dp, density: Density) =
+    performGesture {
+        with(density) {
+            val touchSlop = TouchSlop.toIntPx()
+            val xPx = x.toIntPx()
+            val yPx = y.toIntPx()
+            val offsetX = if (xPx > 0) xPx + touchSlop else if (xPx < 0) xPx - touchSlop else 0
+            val offsetY = if (yPx > 0) yPx + touchSlop else if (yPx < 0) yPx - touchSlop else 0
+            swipeWithVelocity(
+                start = center,
+                end = Offset(center.x - offsetX, center.y - offsetY),
+                endVelocity = 0f
+            )
+        }
+    }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyForIndexedTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyForIndexedTest.kt
deleted file mode 100644
index 37c72b8..0000000
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyForIndexedTest.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2020 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.compose.foundation.lazy
-
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.preferredHeight
-import androidx.compose.foundation.layout.preferredWidth
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.text.BasicText
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
-import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithText
-import androidx.compose.ui.unit.dp
-import org.junit.Rule
-import org.junit.Test
-
-class LazyForIndexedTest {
-
-    @get:Rule
-    val rule = createComposeRule()
-
-    @Test
-    fun columnWithIndexesComposedWithCorrectIndexAndItem() {
-        val items = (0..1).map { it.toString() }
-
-        rule.setContent {
-            LazyColumnForIndexed(items, Modifier.preferredHeight(200.dp)) { index, item ->
-                BasicText("${index}x$item", Modifier.fillParentMaxWidth().height(100.dp))
-            }
-        }
-
-        rule.onNodeWithText("0x0")
-            .assertTopPositionInRootIsEqualTo(0.dp)
-
-        rule.onNodeWithText("1x1")
-            .assertTopPositionInRootIsEqualTo(100.dp)
-    }
-
-    @Test
-    fun rowWithIndexesComposedWithCorrectIndexAndItem() {
-        val items = (0..1).map { it.toString() }
-
-        rule.setContent {
-            LazyRowForIndexed(items, Modifier.preferredWidth(200.dp)) { index, item ->
-                BasicText("${index}x$item", Modifier.fillParentMaxHeight().width(100.dp))
-            }
-        }
-
-        rule.onNodeWithText("0x0")
-            .assertLeftPositionInRootIsEqualTo(0.dp)
-
-        rule.onNodeWithText("1x1")
-            .assertLeftPositionInRootIsEqualTo(100.dp)
-    }
-}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt
index c77dee6..8b33fbf 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt
@@ -68,11 +68,10 @@
         val smallPaddingSize = itemSize / 4
         val largePaddingSize = itemSize
         rule.setContent {
-            LazyColumnFor(
-                items = listOf(1),
-                state = rememberLazyListState().also { state = it },
+            LazyColumn(
                 modifier = Modifier.size(containerSize)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     start = smallPaddingSize,
                     top = largePaddingSize,
@@ -80,7 +79,9 @@
                     bottom = largePaddingSize
                 )
             ) {
-                Spacer(Modifier.fillParentMaxWidth().preferredHeight(itemSize).testTag(ItemTag))
+                items(listOf(1)) {
+                    Spacer(Modifier.fillParentMaxWidth().preferredHeight(itemSize).testTag(ItemTag))
+                }
             }
         }
 
@@ -101,17 +102,18 @@
     fun column_contentPaddingIsNotAffectingScrollPosition() {
         lateinit var state: LazyListState
         rule.setContent {
-            LazyColumnFor(
-                items = listOf(1),
-                state = rememberLazyListState().also { state = it },
+            LazyColumn(
                 modifier = Modifier.size(itemSize * 2)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     top = itemSize,
                     bottom = itemSize
                 )
             ) {
-                Spacer(Modifier.fillParentMaxWidth().preferredHeight(itemSize).testTag(ItemTag))
+                items(listOf(1)) {
+                    Spacer(Modifier.fillParentMaxWidth().preferredHeight(itemSize).testTag(ItemTag))
+                }
             }
         }
 
@@ -127,17 +129,18 @@
         lateinit var state: LazyListState
         val padding = itemSize * 1.5f
         rule.setContent {
-            LazyColumnFor(
-                items = (0..3).toList(),
-                state = rememberLazyListState().also { state = it },
+            LazyColumn(
                 modifier = Modifier.size(padding * 2 + itemSize)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     top = padding,
                     bottom = padding
                 )
             ) {
-                Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                items((0..3).toList()) {
+                    Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                }
             }
         }
 
@@ -167,17 +170,18 @@
         lateinit var state: LazyListState
         val padding = itemSize * 1.5f
         rule.setContent {
-            LazyColumnFor(
-                items = (0..3).toList(),
-                state = rememberLazyListState().also { state = it },
+            LazyColumn(
                 modifier = Modifier.size(itemSize + padding * 2)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     top = padding,
                     bottom = padding
                 )
             ) {
-                Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                items((0..3).toList()) {
+                    Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                }
             }
         }
 
@@ -201,17 +205,18 @@
         lateinit var state: LazyListState
         val padding = itemSize * 1.5f
         rule.setContent {
-            LazyColumnFor(
-                items = (0..3).toList(),
-                state = rememberLazyListState().also { state = it },
+            LazyColumn(
                 modifier = Modifier.size(padding * 2 + itemSize)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     top = padding,
                     bottom = padding
                 )
             ) {
-                Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                items((0..3).toList()) {
+                    Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                }
             }
         }
 
@@ -244,17 +249,18 @@
         lateinit var state: LazyListState
         val padding = itemSize * 1.5f
         rule.setContent {
-            LazyColumnFor(
-                items = (0..3).toList(),
-                state = rememberLazyListState().also { state = it },
+            LazyColumn(
                 modifier = Modifier.size(padding * 2 + itemSize)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     top = padding,
                     bottom = padding
                 )
             ) {
-                Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                items((0..3).toList()) {
+                    Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                }
             }
         }
 
@@ -275,8 +281,7 @@
     fun column_contentPaddingAndWrapContent() {
         rule.setContent {
             Box(modifier = Modifier.testTag(ContainerTag)) {
-                LazyColumnFor(
-                    items = listOf(1),
+                LazyColumn(
                     contentPadding = PaddingValues(
                         start = 2.dp,
                         top = 4.dp,
@@ -284,7 +289,9 @@
                         bottom = 8.dp
                     )
                 ) {
-                    Spacer(Modifier.size(itemSize).testTag(ItemTag))
+                    items(listOf(1)) {
+                        Spacer(Modifier.size(itemSize).testTag(ItemTag))
+                    }
                 }
             }
         }
@@ -306,8 +313,7 @@
     fun column_contentPaddingAndNoContent() {
         rule.setContent {
             Box(modifier = Modifier.testTag(ContainerTag)) {
-                LazyColumnFor(
-                    items = listOf(0),
+                LazyColumn(
                     contentPadding = PaddingValues(
                         start = 2.dp,
                         top = 4.dp,
@@ -315,6 +321,8 @@
                         bottom = 8.dp
                     )
                 ) {
+                    items(listOf(0)) {
+                    }
                 }
             }
         }
@@ -333,11 +341,10 @@
         val smallPaddingSize = itemSize / 4
         val largePaddingSize = itemSize
         rule.setContent {
-            LazyRowFor(
-                items = listOf(1),
-                state = rememberLazyListState().also { state = it },
+            LazyRow(
                 modifier = Modifier.size(containerSize)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     top = smallPaddingSize,
                     start = largePaddingSize,
@@ -345,7 +352,9 @@
                     end = largePaddingSize
                 )
             ) {
-                Spacer(Modifier.fillParentMaxHeight().preferredWidth(itemSize).testTag(ItemTag))
+                items(listOf(1)) {
+                    Spacer(Modifier.fillParentMaxHeight().preferredWidth(itemSize).testTag(ItemTag))
+                }
             }
         }
 
@@ -369,17 +378,18 @@
             50.dp.toIntPx().toDp()
         }
         rule.setContent {
-            LazyRowFor(
-                items = listOf(1),
-                state = rememberLazyListState().also { state = it },
+            LazyRow(
                 modifier = Modifier.size(itemSize * 2)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     start = itemSize,
                     end = itemSize
                 )
             ) {
-                Spacer(Modifier.fillParentMaxHeight().preferredWidth(itemSize).testTag(ItemTag))
+                items(listOf(1)) {
+                    Spacer(Modifier.fillParentMaxHeight().preferredWidth(itemSize).testTag(ItemTag))
+                }
             }
         }
 
@@ -395,17 +405,18 @@
         lateinit var state: LazyListState
         val padding = itemSize * 1.5f
         rule.setContent {
-            LazyRowFor(
-                items = (0..3).toList(),
-                state = rememberLazyListState().also { state = it },
+            LazyRow(
                 modifier = Modifier.size(padding * 2 + itemSize)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     start = padding,
                     end = padding
                 )
             ) {
-                Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                items((0..3).toList()) {
+                    Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                }
             }
         }
 
@@ -435,17 +446,18 @@
         lateinit var state: LazyListState
         val padding = itemSize * 1.5f
         rule.setContent {
-            LazyRowFor(
-                items = (0..3).toList(),
-                state = rememberLazyListState().also { state = it },
+            LazyRow(
                 modifier = Modifier.size(itemSize + padding * 2)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     start = padding,
                     end = padding
                 )
             ) {
-                Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                items((0..3).toList()) {
+                    Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                }
             }
         }
 
@@ -469,17 +481,18 @@
         lateinit var state: LazyListState
         val padding = itemSize * 1.5f
         rule.setContent {
-            LazyRowFor(
-                items = (0..3).toList(),
-                state = rememberLazyListState().also { state = it },
+            LazyRow(
                 modifier = Modifier.size(padding * 2 + itemSize)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     start = padding,
                     end = padding
                 )
             ) {
-                Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                items((0..3).toList()) {
+                    Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                }
             }
         }
 
@@ -512,17 +525,18 @@
         lateinit var state: LazyListState
         val padding = itemSize * 1.5f
         rule.setContent {
-            LazyRowFor(
-                items = (0..3).toList(),
-                state = rememberLazyListState().also { state = it },
+            LazyRow(
                 modifier = Modifier.size(padding * 2 + itemSize)
                     .testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     start = padding,
                     end = padding
                 )
             ) {
-                Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                items((0..3).toList()) {
+                    Spacer(Modifier.size(itemSize).testTag(it.toString()))
+                }
             }
         }
 
@@ -543,8 +557,7 @@
     fun row_contentPaddingAndWrapContent() {
         rule.setContent {
             Box(modifier = Modifier.testTag(ContainerTag)) {
-                LazyRowFor(
-                    items = listOf(1),
+                LazyRow(
                     contentPadding = PaddingValues(
                         start = 2.dp,
                         top = 4.dp,
@@ -552,7 +565,9 @@
                         bottom = 8.dp
                     )
                 ) {
-                    Spacer(Modifier.size(itemSize).testTag(ItemTag))
+                    items(listOf(1)) {
+                        Spacer(Modifier.size(itemSize).testTag(ItemTag))
+                    }
                 }
             }
         }
@@ -574,8 +589,7 @@
     fun row_contentPaddingAndNoContent() {
         rule.setContent {
             Box(modifier = Modifier.testTag(ContainerTag)) {
-                LazyRowFor(
-                    items = listOf(0),
+                LazyRow(
                     contentPadding = PaddingValues(
                         start = 2.dp,
                         top = 4.dp,
@@ -583,6 +597,7 @@
                         bottom = 8.dp
                     )
                 ) {
+                    items(listOf(0)) {}
                 }
             }
         }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsIndexedTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsIndexedTest.kt
new file mode 100644
index 0000000..16bb089
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsIndexedTest.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2020 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.compose.foundation.lazy
+
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.preferredHeight
+import androidx.compose.foundation.layout.preferredWidth
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
+import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.unit.dp
+import org.junit.Rule
+import org.junit.Test
+
+class LazyListsIndexedTest {
+
+    @get:Rule
+    val rule = createComposeRule()
+
+    @Test
+    fun lazyColumnShowsIndexedItems() {
+        val items = (1..4).map { it.toString() }
+
+        rule.setContent {
+            LazyColumn(Modifier.preferredHeight(200.dp)) {
+                itemsIndexed(items) { index, item ->
+                    Spacer(
+                        Modifier.preferredHeight(101.dp).fillParentMaxWidth()
+                            .testTag("$index-$item")
+                    )
+                }
+            }
+        }
+
+        rule.onNodeWithTag("0-1")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("1-2")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("2-3")
+            .assertDoesNotExist()
+
+        rule.onNodeWithTag("3-4")
+            .assertDoesNotExist()
+    }
+
+    @Test
+    fun columnWithIndexesComposedWithCorrectIndexAndItem() {
+        val items = (0..1).map { it.toString() }
+
+        rule.setContent {
+            LazyColumn(Modifier.preferredHeight(200.dp)) {
+                itemsIndexed(items) { index, item ->
+                    BasicText("${index}x$item", Modifier.fillParentMaxWidth().height(100.dp))
+                }
+            }
+        }
+
+        rule.onNodeWithText("0x0")
+            .assertTopPositionInRootIsEqualTo(0.dp)
+
+        rule.onNodeWithText("1x1")
+            .assertTopPositionInRootIsEqualTo(100.dp)
+    }
+
+    @Test
+    fun lazyRowShowsIndexedItems() {
+        val items = (1..4).map { it.toString() }
+
+        rule.setContent {
+            LazyRow(Modifier.preferredWidth(200.dp)) {
+                itemsIndexed(items) { index, item ->
+                    Spacer(
+                        Modifier.preferredWidth(101.dp).fillParentMaxHeight()
+                            .testTag("$index-$item")
+                    )
+                }
+            }
+        }
+
+        rule.onNodeWithTag("0-1")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("1-2")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("2-3")
+            .assertDoesNotExist()
+
+        rule.onNodeWithTag("3-4")
+            .assertDoesNotExist()
+    }
+
+    @Test
+    fun rowWithIndexesComposedWithCorrectIndexAndItem() {
+        val items = (0..1).map { it.toString() }
+
+        rule.setContent {
+            LazyRow(Modifier.preferredWidth(200.dp)) {
+                itemsIndexed(items) { index, item ->
+                    BasicText("${index}x$item", Modifier.fillParentMaxHeight().width(100.dp))
+                }
+            }
+        }
+
+        rule.onNodeWithText("0x0")
+            .assertLeftPositionInRootIsEqualTo(0.dp)
+
+        rule.onNodeWithText("1x1")
+            .assertLeftPositionInRootIsEqualTo(100.dp)
+    }
+}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyNestedScrollingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyNestedScrollingTest.kt
index 769791b..fca6c58 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyNestedScrollingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyNestedScrollingTest.kt
@@ -72,11 +72,10 @@
                     }
                 )
             ) {
-                LazyColumnFor(
-                    items = items,
-                    modifier = Modifier.size(100.dp).testTag(LazyTag)
-                ) {
-                    Spacer(Modifier.size(50.dp).testTag("$it"))
+                LazyColumn(Modifier.size(100.dp).testTag(LazyTag)) {
+                    items(items) {
+                        Spacer(Modifier.size(50.dp).testTag("$it"))
+                    }
                 }
             }
         }
@@ -107,11 +106,10 @@
                     }
                 )
             ) {
-                LazyColumnFor(
-                    items = items,
-                    modifier = Modifier.size(100.dp).testTag(LazyTag)
-                ) {
-                    Spacer(Modifier.size(50.dp).testTag("$it"))
+                LazyColumn(Modifier.size(100.dp).testTag(LazyTag)) {
+                    items(items) {
+                        Spacer(Modifier.size(50.dp).testTag("$it"))
+                    }
                 }
             }
         }
@@ -152,11 +150,10 @@
                     }
                 )
             ) {
-                LazyColumnFor(
-                    items = items,
-                    modifier = Modifier.size(100.dp).testTag(LazyTag)
-                ) {
-                    Spacer(Modifier.size(40.dp).testTag("$it"))
+                LazyColumn(Modifier.size(100.dp).testTag(LazyTag)) {
+                    items(items) {
+                        Spacer(Modifier.size(40.dp).testTag("$it"))
+                    }
                 }
             }
         }
@@ -187,11 +184,10 @@
                     }
                 )
             ) {
-                LazyColumnFor(
-                    items = items,
-                    modifier = Modifier.size(100.dp).testTag(LazyTag)
-                ) {
-                    Spacer(Modifier.size(50.dp).testTag("$it"))
+                LazyColumn(Modifier.size(100.dp).testTag(LazyTag)) {
+                    items(items) {
+                        Spacer(Modifier.size(50.dp).testTag("$it"))
+                    }
                 }
             }
         }
@@ -227,11 +223,12 @@
                     }
                 )
             ) {
-                LazyRowFor(
-                    items = items,
+                LazyRow(
                     modifier = Modifier.size(100.dp).testTag(LazyTag)
                 ) {
-                    Spacer(Modifier.size(50.dp).testTag("$it"))
+                    items(items) {
+                        Spacer(Modifier.size(50.dp).testTag("$it"))
+                    }
                 }
             }
         }
@@ -262,11 +259,12 @@
                     }
                 )
             ) {
-                LazyRowFor(
-                    items = items,
+                LazyRow(
                     modifier = Modifier.size(100.dp).testTag(LazyTag)
                 ) {
-                    Spacer(Modifier.size(50.dp).testTag("$it"))
+                    items(items) {
+                        Spacer(Modifier.size(50.dp).testTag("$it"))
+                    }
                 }
             }
         }
@@ -307,11 +305,12 @@
                     }
                 )
             ) {
-                LazyRowFor(
-                    items = items,
+                LazyRow(
                     modifier = Modifier.size(100.dp).testTag(LazyTag)
                 ) {
-                    Spacer(Modifier.size(40.dp).testTag("$it"))
+                    items(items) {
+                        Spacer(Modifier.size(40.dp).testTag("$it"))
+                    }
                 }
             }
         }
@@ -342,11 +341,12 @@
                     }
                 )
             ) {
-                LazyRowFor(
-                    items = items,
+                LazyRow(
                     modifier = Modifier.size(100.dp).testTag(LazyTag)
                 ) {
-                    Spacer(Modifier.size(50.dp).testTag("$it"))
+                    items(items) {
+                        Spacer(Modifier.size(50.dp).testTag("$it"))
+                    }
                 }
             }
         }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowForTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowForTest.kt
deleted file mode 100644
index f4d3fd4..0000000
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowForTest.kt
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- * Copyright 2020 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.compose.foundation.lazy
-
-import androidx.compose.animation.core.snap
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.preferredSize
-import androidx.compose.foundation.layout.preferredWidth
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.sizeIn
-import androidx.compose.foundation.layout.width
-import androidx.compose.runtime.Providers
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawBehind
-import androidx.compose.ui.platform.AmbientLayoutDirection
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.SemanticsNodeInteraction
-import androidx.compose.ui.test.assertHeightIsEqualTo
-import androidx.compose.ui.test.assertIsDisplayed
-import androidx.compose.ui.test.assertIsEqualTo
-import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
-import androidx.compose.ui.test.assertPositionInRootIsEqualTo
-import androidx.compose.ui.test.assertWidthIsEqualTo
-import androidx.compose.ui.test.getUnclippedBoundsInRoot
-import androidx.compose.ui.test.junit4.StateRestorationTester
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.dp
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.MediumTest
-import com.google.common.truth.Truth
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.runBlocking
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@MediumTest
-@RunWith(AndroidJUnit4::class)
-class LazyRowForTest {
-    private val LazyRowForTag = "LazyRowForTag"
-
-    @get:Rule
-    val rule = createComposeRule()
-
-    @Test
-    fun lazyRowOnlyVisibleItemsAdded() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            Box(Modifier.preferredWidth(200.dp)) {
-                LazyRowFor(items) {
-                    Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag("1")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("4")
-            .assertDoesNotExist()
-    }
-
-    @Test
-    fun lazyRowScrollToShowItems123() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            Box(Modifier.preferredWidth(200.dp)) {
-                LazyRowFor(items, Modifier.testTag(LazyRowForTag)) {
-                    Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 50.dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("4")
-            .assertDoesNotExist()
-    }
-
-    @Test
-    fun lazyRowScrollToHideFirstItem() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            Box(Modifier.preferredWidth(200.dp)) {
-                LazyRowFor(items, Modifier.testTag(LazyRowForTag)) {
-                    Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 102.dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertIsDisplayed()
-    }
-
-    @Test
-    fun lazyRowScrollToShowItems234() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            Box(Modifier.preferredWidth(200.dp)) {
-                LazyRowFor(items, Modifier.testTag(LazyRowForTag)) {
-                    Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 150.dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("4")
-            .assertIsDisplayed()
-    }
-
-    @Test
-    fun lazyRowWrapsContent() = with(rule.density) {
-        val itemInsideLazyRow = "itemInsideLazyRow"
-        val itemOutsideLazyRow = "itemOutsideLazyRow"
-        var sameSizeItems by mutableStateOf(true)
-
-        rule.setContent {
-            Column {
-                LazyRowFor(
-                    items = listOf(1, 2),
-                    modifier = Modifier.testTag(LazyRowForTag)
-                ) {
-                    if (it == 1) {
-                        Spacer(Modifier.preferredSize(50.dp).testTag(itemInsideLazyRow))
-                    } else {
-                        Spacer(Modifier.preferredSize(if (sameSizeItems) 50.dp else 70.dp))
-                    }
-                }
-                Spacer(Modifier.preferredSize(50.dp).testTag(itemOutsideLazyRow))
-            }
-        }
-
-        rule.onNodeWithTag(itemInsideLazyRow)
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag(itemOutsideLazyRow)
-            .assertIsDisplayed()
-
-        var lazyRowBounds = rule.onNodeWithTag(LazyRowForTag)
-            .getUnclippedBoundsInRoot()
-
-        assertThat(lazyRowBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-        assertThat(lazyRowBounds.right.toIntPx()).isWithin1PixelFrom(100.dp.toIntPx())
-        assertThat(lazyRowBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-        assertThat(lazyRowBounds.bottom.toIntPx()).isWithin1PixelFrom(50.dp.toIntPx())
-
-        rule.runOnIdle {
-            sameSizeItems = false
-        }
-
-        rule.waitForIdle()
-
-        rule.onNodeWithTag(itemInsideLazyRow)
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag(itemOutsideLazyRow)
-            .assertIsDisplayed()
-
-        lazyRowBounds = rule.onNodeWithTag(LazyRowForTag)
-            .getUnclippedBoundsInRoot()
-
-        assertThat(lazyRowBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-        assertThat(lazyRowBounds.right.toIntPx()).isWithin1PixelFrom(120.dp.toIntPx())
-        assertThat(lazyRowBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-        assertThat(lazyRowBounds.bottom.toIntPx()).isWithin1PixelFrom(70.dp.toIntPx())
-    }
-
-    private val firstItemTag = "firstItemTag"
-    private val secondItemTag = "secondItemTag"
-
-    private fun prepareLazyRowForAlignment(verticalGravity: Alignment.Vertical) {
-        rule.setContent {
-            LazyRowFor(
-                items = listOf(1, 2),
-                modifier = Modifier.testTag(LazyRowForTag).height(100.dp),
-                verticalAlignment = verticalGravity
-            ) {
-                if (it == 1) {
-                    Spacer(Modifier.preferredSize(50.dp).testTag(firstItemTag))
-                } else {
-                    Spacer(Modifier.preferredSize(70.dp).testTag(secondItemTag))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag(secondItemTag)
-            .assertIsDisplayed()
-
-        val lazyRowBounds = rule.onNodeWithTag(LazyRowForTag)
-            .getUnclippedBoundsInRoot()
-
-        with(rule.density) {
-            // Verify the height of the row
-            assertThat(lazyRowBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
-            assertThat(lazyRowBounds.bottom.toIntPx()).isWithin1PixelFrom(100.dp.toIntPx())
-        }
-    }
-
-    @Test
-    fun lazyRowAlignmentCenterVertically() {
-        prepareLazyRowForAlignment(Alignment.CenterVertically)
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertPositionInRootIsEqualTo(0.dp, 25.dp)
-
-        rule.onNodeWithTag(secondItemTag)
-            .assertPositionInRootIsEqualTo(50.dp, 15.dp)
-    }
-
-    @Test
-    fun lazyRowAlignmentTop() {
-        prepareLazyRowForAlignment(Alignment.Top)
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertPositionInRootIsEqualTo(0.dp, 0.dp)
-
-        rule.onNodeWithTag(secondItemTag)
-            .assertPositionInRootIsEqualTo(50.dp, 0.dp)
-    }
-
-    @Test
-    fun lazyRowAlignmentBottom() {
-        prepareLazyRowForAlignment(Alignment.Bottom)
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertPositionInRootIsEqualTo(0.dp, 50.dp)
-
-        rule.onNodeWithTag(secondItemTag)
-            .assertPositionInRootIsEqualTo(50.dp, 30.dp)
-    }
-
-    @Test
-    fun itemFillingParentWidth() {
-        rule.setContent {
-            LazyRowFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.fillParentMaxWidth().height(50.dp).testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(100.dp)
-            .assertHeightIsEqualTo(50.dp)
-    }
-
-    @Test
-    fun itemFillingParentHeight() {
-        rule.setContent {
-            LazyRowFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.width(50.dp).fillParentMaxHeight().testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(50.dp)
-            .assertHeightIsEqualTo(150.dp)
-    }
-
-    @Test
-    fun itemFillingParentSize() {
-        rule.setContent {
-            LazyRowFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(100.dp)
-            .assertHeightIsEqualTo(150.dp)
-    }
-
-    @Test
-    fun itemFillingParentWidthFraction() {
-        rule.setContent {
-            LazyRowFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.fillParentMaxWidth(0.7f).height(50.dp).testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(70.dp)
-            .assertHeightIsEqualTo(50.dp)
-    }
-
-    @Test
-    fun itemFillingParentHeightFraction() {
-        rule.setContent {
-            LazyRowFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.width(50.dp).fillParentMaxHeight(0.3f).testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(50.dp)
-            .assertHeightIsEqualTo(45.dp)
-    }
-
-    @Test
-    fun itemFillingParentSizeFraction() {
-        rule.setContent {
-            LazyRowFor(
-                items = listOf(0),
-                modifier = Modifier.size(width = 100.dp, height = 150.dp)
-            ) {
-                Spacer(Modifier.fillParentMaxSize(0.5f).testTag(firstItemTag))
-            }
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(50.dp)
-            .assertHeightIsEqualTo(75.dp)
-    }
-
-    @Test
-    fun itemFillingParentSizeParentResized() {
-        var parentSize by mutableStateOf(100.dp)
-        rule.setContent {
-            LazyRowFor(
-                items = listOf(0),
-                modifier = Modifier.size(parentSize)
-            ) {
-                Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
-            }
-        }
-
-        rule.runOnIdle {
-            parentSize = 150.dp
-        }
-
-        rule.onNodeWithTag(firstItemTag)
-            .assertWidthIsEqualTo(150.dp)
-            .assertHeightIsEqualTo(150.dp)
-    }
-
-    @Test
-    fun scrollsLeftInRtl() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            Providers(AmbientLayoutDirection provides LayoutDirection.Rtl) {
-                Box(Modifier.preferredWidth(100.dp)) {
-                    LazyRowFor(items, Modifier.testTag(LazyRowForTag)) {
-                        Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
-                    }
-                }
-            }
-        }
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = (-150).dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-    }
-
-    @Test
-    fun whenNotAnymoreAvailableItemWasDisplayed() {
-        var items by mutableStateOf((1..30).toList())
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // after scroll we will display items 16-20
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 300.dp, density = rule.density)
-
-        rule.runOnIdle {
-            items = (1..10).toList()
-        }
-
-        // there is no item 16 anymore so we will just display the last items 6-10
-        rule.onNodeWithTag("6")
-            .assertLeftPositionIsAlmost(0.dp)
-    }
-
-    @Test
-    fun whenFewDisplayedItemsWereRemoved() {
-        var items by mutableStateOf((1..10).toList())
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // after scroll we will display items 6-10
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 100.dp, density = rule.density)
-
-        rule.runOnIdle {
-            items = (1..8).toList()
-        }
-
-        // there are no more items 9 and 10, so we have to scroll back
-        rule.onNodeWithTag("4")
-            .assertLeftPositionIsAlmost(0.dp)
-    }
-
-    @Test
-    fun whenItemsBecameEmpty() {
-        var items by mutableStateOf((1..10).toList())
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.sizeIn(maxHeight = 100.dp).testTag(LazyRowForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // after scroll we will display items 2-6
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 20.dp, density = rule.density)
-
-        rule.runOnIdle {
-            items = emptyList()
-        }
-
-        // there are no more items so the LazyRow is zero sized
-        rule.onNodeWithTag(LazyRowForTag)
-            .assertWidthIsEqualTo(0.dp)
-            .assertHeightIsEqualTo(0.dp)
-
-        // and has no children
-        rule.onNodeWithTag("1")
-            .assertDoesNotExist()
-        rule.onNodeWithTag("2")
-            .assertDoesNotExist()
-    }
-
-    @Test
-    fun scrollBackAndForth() {
-        val items by mutableStateOf((1..20).toList())
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // after scroll we will display items 6-10
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 100.dp, density = rule.density)
-
-        // and scroll back
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = (-100).dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertLeftPositionIsAlmost(0.dp)
-    }
-
-    @Test
-    fun tryToScrollBackwardWhenAlreadyOnTop() {
-        val items by mutableStateOf((1..20).toList())
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag)
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        // we already displaying the first item, so this should do nothing
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = (-50).dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertLeftPositionIsAlmost(0.dp)
-        rule.onNodeWithTag("5")
-            .assertLeftPositionIsAlmost(80.dp)
-    }
-
-    private fun SemanticsNodeInteraction.assertLeftPositionIsAlmost(expected: Dp) {
-        getUnclippedBoundsInRoot().left.assertIsEqualTo(expected, tolerance = 1.dp)
-    }
-
-    @Test
-    fun contentOfNotStableItemsIsNotRecomposedDuringScroll() {
-        val items = listOf(NotStable(1), NotStable(2))
-        var firstItemRecomposed = 0
-        var secondItemRecomposed = 0
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag)
-            ) {
-                if (it.count == 1) {
-                    firstItemRecomposed++
-                } else {
-                    secondItemRecomposed++
-                }
-                Spacer(Modifier.size(75.dp))
-            }
-        }
-
-        rule.runOnIdle {
-            assertThat(firstItemRecomposed).isEqualTo(1)
-            assertThat(secondItemRecomposed).isEqualTo(1)
-        }
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = (50).dp, density = rule.density)
-
-        rule.runOnIdle {
-            assertThat(firstItemRecomposed).isEqualTo(1)
-            assertThat(secondItemRecomposed).isEqualTo(1)
-        }
-    }
-
-    @Test
-    fun onlyOneMeasurePassForScrollEvent() {
-        val items by mutableStateOf((1..20).toList())
-        lateinit var state: LazyListState
-        rule.setContent {
-            state = rememberLazyListState()
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        val initialMeasurePasses = state.numMeasurePasses
-
-        rule.runOnIdle {
-            with(rule.density) {
-                state.onScroll(-110.dp.toPx())
-            }
-        }
-
-        rule.waitForIdle()
-
-        assertThat(state.numMeasurePasses).isEqualTo(initialMeasurePasses + 1)
-    }
-
-    @Test
-    fun stateUpdatedAfterScroll() {
-        val items by mutableStateOf((1..20).toList())
-        lateinit var state: LazyListState
-        rule.setContent {
-            state = rememberLazyListState()
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.runOnIdle {
-            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
-            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
-        }
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 30.dp, density = rule.density)
-
-        rule.runOnIdle {
-            assertThat(state.firstVisibleItemIndex).isEqualTo(1)
-
-            with(rule.density) {
-                // TODO(b/169232491): test scrolling doesn't appear to be scrolling exactly the right
-                //  number of pixels
-                val expectedOffset = 10.dp.toIntPx()
-                val tolerance = 2.dp.toIntPx()
-                assertThat(state.firstVisibleItemScrollOffset).isEqualTo(expectedOffset, tolerance)
-            }
-        }
-    }
-
-    @Test
-    fun stateUpdatedAfterScrollWithinTheSameItem() {
-        val items by mutableStateOf((1..20).toList())
-        lateinit var state: LazyListState
-        rule.setContent {
-            state = rememberLazyListState()
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 10.dp, density = rule.density)
-
-        rule.runOnIdle {
-            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
-            with(rule.density) {
-                val expectedOffset = 10.dp.toIntPx()
-                val tolerance = 2.dp.toIntPx()
-                assertThat(state.firstVisibleItemScrollOffset)
-                    .isEqualTo(expectedOffset, tolerance)
-            }
-        }
-    }
-
-    @Test
-    fun initialScrollIsApplied() {
-        val items by mutableStateOf((0..20).toList())
-        lateinit var state: LazyListState
-        val expectedOffset = with(rule.density) { 10.dp.toIntPx() }
-        rule.setContent {
-            state = rememberLazyListState(2, expectedOffset)
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.runOnIdle {
-            assertThat(state.firstVisibleItemIndex).isEqualTo(2)
-            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(expectedOffset)
-        }
-
-        rule.onNodeWithTag("2")
-            .assertLeftPositionInRootIsEqualTo((-10).dp)
-    }
-
-    @Test
-    fun stateIsRestored() {
-        val restorationTester = StateRestorationTester(rule)
-        val items by mutableStateOf((1..20).toList())
-        var state: LazyListState? = null
-        restorationTester.setContent {
-            state = rememberLazyListState()
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag),
-                state = state!!
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 30.dp, density = rule.density)
-
-        val (index, scrollOffset) = rule.runOnIdle {
-            state!!.firstVisibleItemIndex to state!!.firstVisibleItemScrollOffset
-        }
-
-        state = null
-
-        restorationTester.emulateSavedInstanceStateRestore()
-
-        rule.runOnIdle {
-            assertThat(state!!.firstVisibleItemIndex).isEqualTo(index)
-            assertThat(state!!.firstVisibleItemScrollOffset).isEqualTo(scrollOffset)
-        }
-    }
-
-    @Test
-    fun snapToItemIndex() {
-        val items by mutableStateOf((1..20).toList())
-        lateinit var state: LazyListState
-        rule.setContent {
-            state = rememberLazyListState()
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag),
-                state = state
-            ) {
-                Spacer(Modifier.size(20.dp).testTag("$it"))
-            }
-        }
-
-        rule.runOnIdle {
-            runBlocking {
-                state.snapToItemIndex(3, 10)
-            }
-            assertThat(state.firstVisibleItemIndex).isEqualTo(3)
-            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(10)
-        }
-    }
-
-    @Test
-    fun itemsAreNotRedrawnDuringScroll() {
-        val items = (0..20).toList()
-        val redrawCount = Array(6) { 0 }
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag)
-            ) {
-                Spacer(
-                    Modifier.size(20.dp)
-                        .drawBehind { redrawCount[it]++ }
-                )
-            }
-        }
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .scrollBy(x = 10.dp, density = rule.density)
-
-        rule.runOnIdle {
-            redrawCount.forEachIndexed { index, i ->
-                Truth.assertWithMessage("Item with index $index was redrawn $i times")
-                    .that(i).isEqualTo(1)
-            }
-        }
-    }
-
-    @Test
-    fun itemInvalidationIsNotCausingAnotherItemToRedraw() {
-        val items = (0..1).toList()
-        val redrawCount = Array(2) { 0 }
-        var stateUsedInDrawScope by mutableStateOf(false)
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                modifier = Modifier.size(100.dp).testTag(LazyRowForTag)
-            ) {
-                Spacer(
-                    Modifier.size(50.dp)
-                        .drawBehind {
-                            redrawCount[it]++
-                            if (it == 1) {
-                                stateUsedInDrawScope.hashCode()
-                            }
-                        }
-                )
-            }
-        }
-
-        rule.runOnIdle {
-            stateUsedInDrawScope = true
-        }
-
-        rule.runOnIdle {
-            Truth.assertWithMessage("First items is not expected to be redrawn")
-                .that(redrawCount[0]).isEqualTo(1)
-            Truth.assertWithMessage("Second items is expected to be redrawn")
-                .that(redrawCount[1]).isEqualTo(2)
-        }
-    }
-
-    @Test
-    fun notVisibleAnymoreItemNotAffectingCrossAxisSize() {
-        val items = (0..1).toList()
-        val itemSize = with(rule.density) { 30.toDp() }
-        val itemSizeMinusOne = with(rule.density) { 29.toDp() }
-        lateinit var state: LazyListState
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                state = rememberLazyListState().also { state = it },
-                modifier = Modifier.width(itemSizeMinusOne).testTag(LazyRowForTag)
-            ) {
-                Spacer(
-                    if (it == 0) {
-                        Modifier.height(30.dp).width(itemSizeMinusOne)
-                    } else {
-                        Modifier.height(20.dp).width(itemSize)
-                    }
-                )
-            }
-        }
-
-        state.scrollBy(itemSize)
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .assertHeightIsEqualTo(20.dp)
-    }
-
-    @Test
-    fun itemStillVisibleAfterOverscrollIsAffectingCrossAxisSize() {
-        val items = (0..2).toList()
-        val itemSize = with(rule.density) { 30.toDp() }
-        lateinit var state: LazyListState
-        rule.setContent {
-            LazyRowFor(
-                items = items,
-                state = rememberLazyListState().also { state = it },
-                modifier = Modifier.width(itemSize * 1.75f).testTag(LazyRowForTag)
-            ) {
-                Spacer(
-                    if (it == 0) {
-                        Modifier.height(30.dp).width(itemSize / 2)
-                    } else if (it == 1) {
-                        Modifier.height(20.dp).width(itemSize / 2)
-                    } else {
-                        Modifier.height(20.dp).width(itemSize)
-                    }
-                )
-            }
-        }
-
-        state.scrollBy(itemSize)
-
-        rule.onNodeWithTag(LazyRowForTag)
-            .assertHeightIsEqualTo(30.dp)
-    }
-
-    private fun LazyListState.scrollBy(offset: Dp) {
-        runBlocking {
-            smoothScrollBy(with(rule.density) { offset.toIntPx().toFloat() }, snap())
-        }
-    }
-}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
index fe720d7..1ab378a 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
@@ -16,17 +16,44 @@
 
 package androidx.compose.foundation.lazy
 
+import androidx.compose.animation.core.snap
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.preferredSize
 import androidx.compose.foundation.layout.preferredWidth
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.sizeIn
+import androidx.compose.foundation.layout.width
+import androidx.compose.runtime.Providers
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.platform.AmbientLayoutDirection
 import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.assertHeightIsEqualTo
 import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertIsEqualTo
+import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
+import androidx.compose.ui.test.assertPositionInRootIsEqualTo
+import androidx.compose.ui.test.assertWidthIsEqualTo
+import androidx.compose.ui.test.getUnclippedBoundsInRoot
+import androidx.compose.ui.test.junit4.StateRestorationTester
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
+import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -34,83 +61,12 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class LazyRowTest {
-    private val LazyRowTag = "LazyRowTag"
+    private val LazyListTag = "LazyListTag"
 
     @get:Rule
     val rule = createComposeRule()
 
     @Test
-    fun lazyRowShowsItem() {
-        val itemTestTag = "itemTestTag"
-
-        rule.setContent {
-            LazyRow {
-                item {
-                    Spacer(
-                        Modifier.preferredWidth(10.dp).fillParentMaxHeight().testTag(itemTestTag)
-                    )
-                }
-            }
-        }
-
-        rule.onNodeWithTag(itemTestTag)
-            .assertIsDisplayed()
-    }
-
-    @Test
-    fun lazyRowShowsItems() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            LazyRow(Modifier.preferredWidth(200.dp)) {
-                items(items) {
-                    Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag("1")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("4")
-            .assertDoesNotExist()
-    }
-
-    @Test
-    fun lazyRowShowsIndexedItems() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            LazyRow(Modifier.preferredWidth(200.dp)) {
-                itemsIndexed(items) { index, item ->
-                    Spacer(
-                        Modifier.preferredWidth(101.dp).fillParentMaxHeight()
-                            .testTag("$index-$item")
-                    )
-                }
-            }
-        }
-
-        rule.onNodeWithTag("0-1")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("1-2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("2-3")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("3-4")
-            .assertDoesNotExist()
-    }
-
-    @Test
     fun lazyRowShowsCombinedItems() {
         val itemTestTag = "itemTestTag"
         val items = listOf(1, 2).map { it.toString() }
@@ -155,59 +111,6 @@
     }
 
     @Test
-    fun lazyRowShowsItemsOnScroll() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            LazyRow(Modifier.preferredWidth(200.dp).testTag(LazyRowTag)) {
-                items(items) {
-                    Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(LazyRowTag)
-            .scrollBy(x = 50.dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("4")
-            .assertDoesNotExist()
-    }
-
-    @Test
-    fun lazyRowScrollHidesItem() {
-        val items = (1..4).map { it.toString() }
-
-        rule.setContent {
-            LazyRow(Modifier.preferredWidth(200.dp).testTag(LazyRowTag)) {
-                items(items) {
-                    Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
-                }
-            }
-        }
-
-        rule.onNodeWithTag(LazyRowTag)
-            .scrollBy(x = 103.dp, density = rule.density)
-
-        rule.onNodeWithTag("1")
-            .assertDoesNotExist()
-
-        rule.onNodeWithTag("2")
-            .assertIsDisplayed()
-
-        rule.onNodeWithTag("3")
-            .assertIsDisplayed()
-    }
-
-    @Test
     fun lazyRowAllowEmptyListItems() {
         val itemTag = "itemTag"
 
@@ -253,4 +156,838 @@
         rule.onNodeWithTag("3")
             .assertDoesNotExist()
     }
-}
\ No newline at end of file
+
+    @Test
+    fun lazyRowOnlyVisibleItemsAdded() {
+        val items = (1..4).map { it.toString() }
+
+        rule.setContent {
+            Box(Modifier.preferredWidth(200.dp)) {
+                LazyRow {
+                    items(items) {
+                        Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag("1")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("2")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("3")
+            .assertDoesNotExist()
+
+        rule.onNodeWithTag("4")
+            .assertDoesNotExist()
+    }
+
+    @Test
+    fun lazyRowScrollToShowItems123() {
+        val items = (1..4).map { it.toString() }
+
+        rule.setContent {
+            Box(Modifier.preferredWidth(200.dp)) {
+                LazyRow(Modifier.testTag(LazyListTag)) {
+                    items(items) {
+                        Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 50.dp, density = rule.density)
+
+        rule.onNodeWithTag("1")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("2")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("3")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("4")
+            .assertDoesNotExist()
+    }
+
+    @Test
+    fun lazyRowScrollToHideFirstItem() {
+        val items = (1..4).map { it.toString() }
+
+        rule.setContent {
+            Box(Modifier.preferredWidth(200.dp)) {
+                LazyRow(Modifier.testTag(LazyListTag)) {
+                    items(items) {
+                        Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 102.dp, density = rule.density)
+
+        rule.onNodeWithTag("1")
+            .assertDoesNotExist()
+
+        rule.onNodeWithTag("2")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("3")
+            .assertIsDisplayed()
+    }
+
+    @Test
+    fun lazyRowScrollToShowItems234() {
+        val items = (1..4).map { it.toString() }
+
+        rule.setContent {
+            Box(Modifier.preferredWidth(200.dp)) {
+                LazyRow(Modifier.testTag(LazyListTag)) {
+                    items(items) {
+                        Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 150.dp, density = rule.density)
+
+        rule.onNodeWithTag("1")
+            .assertDoesNotExist()
+
+        rule.onNodeWithTag("2")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("3")
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag("4")
+            .assertIsDisplayed()
+    }
+
+    @Test
+    fun lazyRowWrapsContent() = with(rule.density) {
+        val itemInsideLazyRow = "itemInsideLazyRow"
+        val itemOutsideLazyRow = "itemOutsideLazyRow"
+        var sameSizeItems by mutableStateOf(true)
+
+        rule.setContent {
+            Column {
+                LazyRow(Modifier.testTag(LazyListTag)) {
+                    items(listOf(1, 2)) {
+                        if (it == 1) {
+                            Spacer(Modifier.preferredSize(50.dp).testTag(itemInsideLazyRow))
+                        } else {
+                            Spacer(Modifier.preferredSize(if (sameSizeItems) 50.dp else 70.dp))
+                        }
+                    }
+                }
+                Spacer(Modifier.preferredSize(50.dp).testTag(itemOutsideLazyRow))
+            }
+        }
+
+        rule.onNodeWithTag(itemInsideLazyRow)
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag(itemOutsideLazyRow)
+            .assertIsDisplayed()
+
+        var lazyRowBounds = rule.onNodeWithTag(LazyListTag)
+            .getUnclippedBoundsInRoot()
+
+        assertThat(lazyRowBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+        assertThat(lazyRowBounds.right.toIntPx()).isWithin1PixelFrom(100.dp.toIntPx())
+        assertThat(lazyRowBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+        assertThat(lazyRowBounds.bottom.toIntPx()).isWithin1PixelFrom(50.dp.toIntPx())
+
+        rule.runOnIdle {
+            sameSizeItems = false
+        }
+
+        rule.waitForIdle()
+
+        rule.onNodeWithTag(itemInsideLazyRow)
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag(itemOutsideLazyRow)
+            .assertIsDisplayed()
+
+        lazyRowBounds = rule.onNodeWithTag(LazyListTag)
+            .getUnclippedBoundsInRoot()
+
+        assertThat(lazyRowBounds.left.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+        assertThat(lazyRowBounds.right.toIntPx()).isWithin1PixelFrom(120.dp.toIntPx())
+        assertThat(lazyRowBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+        assertThat(lazyRowBounds.bottom.toIntPx()).isWithin1PixelFrom(70.dp.toIntPx())
+    }
+
+    private val firstItemTag = "firstItemTag"
+    private val secondItemTag = "secondItemTag"
+
+    private fun prepareLazyRowForAlignment(verticalGravity: Alignment.Vertical) {
+        rule.setContent {
+            LazyRow(
+                Modifier.testTag(LazyListTag).height(100.dp),
+                verticalAlignment = verticalGravity
+            ) {
+                items(listOf(1, 2)) {
+                    if (it == 1) {
+                        Spacer(Modifier.preferredSize(50.dp).testTag(firstItemTag))
+                    } else {
+                        Spacer(Modifier.preferredSize(70.dp).testTag(secondItemTag))
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertIsDisplayed()
+
+        rule.onNodeWithTag(secondItemTag)
+            .assertIsDisplayed()
+
+        val lazyRowBounds = rule.onNodeWithTag(LazyListTag)
+            .getUnclippedBoundsInRoot()
+
+        with(rule.density) {
+            // Verify the height of the row
+            assertThat(lazyRowBounds.top.toIntPx()).isWithin1PixelFrom(0.dp.toIntPx())
+            assertThat(lazyRowBounds.bottom.toIntPx()).isWithin1PixelFrom(100.dp.toIntPx())
+        }
+    }
+
+    @Test
+    fun lazyRowAlignmentCenterVertically() {
+        prepareLazyRowForAlignment(Alignment.CenterVertically)
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertPositionInRootIsEqualTo(0.dp, 25.dp)
+
+        rule.onNodeWithTag(secondItemTag)
+            .assertPositionInRootIsEqualTo(50.dp, 15.dp)
+    }
+
+    @Test
+    fun lazyRowAlignmentTop() {
+        prepareLazyRowForAlignment(Alignment.Top)
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertPositionInRootIsEqualTo(0.dp, 0.dp)
+
+        rule.onNodeWithTag(secondItemTag)
+            .assertPositionInRootIsEqualTo(50.dp, 0.dp)
+    }
+
+    @Test
+    fun lazyRowAlignmentBottom() {
+        prepareLazyRowForAlignment(Alignment.Bottom)
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertPositionInRootIsEqualTo(0.dp, 50.dp)
+
+        rule.onNodeWithTag(secondItemTag)
+            .assertPositionInRootIsEqualTo(50.dp, 30.dp)
+    }
+
+    @Test
+    fun itemFillingParentWidth() {
+        rule.setContent {
+            LazyRow(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxWidth().height(50.dp).testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(100.dp)
+            .assertHeightIsEqualTo(50.dp)
+    }
+
+    @Test
+    fun itemFillingParentHeight() {
+        rule.setContent {
+            LazyRow(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.width(50.dp).fillParentMaxHeight().testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(50.dp)
+            .assertHeightIsEqualTo(150.dp)
+    }
+
+    @Test
+    fun itemFillingParentSize() {
+        rule.setContent {
+            LazyRow(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(100.dp)
+            .assertHeightIsEqualTo(150.dp)
+    }
+
+    @Test
+    fun itemFillingParentWidthFraction() {
+        rule.setContent {
+            LazyRow(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxWidth(0.7f).height(50.dp).testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(70.dp)
+            .assertHeightIsEqualTo(50.dp)
+    }
+
+    @Test
+    fun itemFillingParentHeightFraction() {
+        rule.setContent {
+            LazyRow(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.width(50.dp).fillParentMaxHeight(0.3f).testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(50.dp)
+            .assertHeightIsEqualTo(45.dp)
+    }
+
+    @Test
+    fun itemFillingParentSizeFraction() {
+        rule.setContent {
+            LazyRow(Modifier.size(width = 100.dp, height = 150.dp)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxSize(0.5f).testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(50.dp)
+            .assertHeightIsEqualTo(75.dp)
+    }
+
+    @Test
+    fun itemFillingParentSizeParentResized() {
+        var parentSize by mutableStateOf(100.dp)
+        rule.setContent {
+            LazyRow(Modifier.size(parentSize)) {
+                items(listOf(0)) {
+                    Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            parentSize = 150.dp
+        }
+
+        rule.onNodeWithTag(firstItemTag)
+            .assertWidthIsEqualTo(150.dp)
+            .assertHeightIsEqualTo(150.dp)
+    }
+
+    @Test
+    fun scrollsLeftInRtl() {
+        val items = (1..4).map { it.toString() }
+
+        rule.setContent {
+            Providers(AmbientLayoutDirection provides LayoutDirection.Rtl) {
+                Box(Modifier.preferredWidth(100.dp)) {
+                    LazyRow(Modifier.testTag(LazyListTag)) {
+                        items(items) {
+                            Spacer(
+                                Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it)
+                            )
+                        }
+                    }
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = (-150).dp, density = rule.density)
+
+        rule.onNodeWithTag("1")
+            .assertDoesNotExist()
+
+        rule.onNodeWithTag("2")
+            .assertIsDisplayed()
+    }
+
+    @Test
+    fun whenNotAnymoreAvailableItemWasDisplayed() {
+        var items by mutableStateOf((1..30).toList())
+        rule.setContent {
+            LazyRow(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // after scroll we will display items 16-20
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 300.dp, density = rule.density)
+
+        rule.runOnIdle {
+            items = (1..10).toList()
+        }
+
+        // there is no item 16 anymore so we will just display the last items 6-10
+        rule.onNodeWithTag("6")
+            .assertLeftPositionIsAlmost(0.dp)
+    }
+
+    @Test
+    fun whenFewDisplayedItemsWereRemoved() {
+        var items by mutableStateOf((1..10).toList())
+        rule.setContent {
+            LazyRow(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // after scroll we will display items 6-10
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 100.dp, density = rule.density)
+
+        rule.runOnIdle {
+            items = (1..8).toList()
+        }
+
+        // there are no more items 9 and 10, so we have to scroll back
+        rule.onNodeWithTag("4")
+            .assertLeftPositionIsAlmost(0.dp)
+    }
+
+    @Test
+    fun whenItemsBecameEmpty() {
+        var items by mutableStateOf((1..10).toList())
+        rule.setContent {
+            LazyRow(Modifier.sizeIn(maxHeight = 100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // after scroll we will display items 2-6
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 20.dp, density = rule.density)
+
+        rule.runOnIdle {
+            items = emptyList()
+        }
+
+        // there are no more items so the LazyRow is zero sized
+        rule.onNodeWithTag(LazyListTag)
+            .assertWidthIsEqualTo(0.dp)
+            .assertHeightIsEqualTo(0.dp)
+
+        // and has no children
+        rule.onNodeWithTag("1")
+            .assertDoesNotExist()
+        rule.onNodeWithTag("2")
+            .assertDoesNotExist()
+    }
+
+    @Test
+    fun scrollBackAndForth() {
+        val items by mutableStateOf((1..20).toList())
+        rule.setContent {
+            LazyRow(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // after scroll we will display items 6-10
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 100.dp, density = rule.density)
+
+        // and scroll back
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = (-100).dp, density = rule.density)
+
+        rule.onNodeWithTag("1")
+            .assertLeftPositionIsAlmost(0.dp)
+    }
+
+    @Test
+    fun tryToScrollBackwardWhenAlreadyOnTop() {
+        val items by mutableStateOf((1..20).toList())
+        rule.setContent {
+            LazyRow(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        // we already displaying the first item, so this should do nothing
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = (-50).dp, density = rule.density)
+
+        rule.onNodeWithTag("1")
+            .assertLeftPositionIsAlmost(0.dp)
+        rule.onNodeWithTag("5")
+            .assertLeftPositionIsAlmost(80.dp)
+    }
+
+    private fun SemanticsNodeInteraction.assertLeftPositionIsAlmost(expected: Dp) {
+        getUnclippedBoundsInRoot().left.assertIsEqualTo(expected, tolerance = 1.dp)
+    }
+
+    @Test
+    fun contentOfNotStableItemsIsNotRecomposedDuringScroll() {
+        val items = listOf(NotStable(1), NotStable(2))
+        var firstItemRecomposed = 0
+        var secondItemRecomposed = 0
+        rule.setContent {
+            LazyRow(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    if (it.count == 1) {
+                        firstItemRecomposed++
+                    } else {
+                        secondItemRecomposed++
+                    }
+                    Spacer(Modifier.size(75.dp))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(firstItemRecomposed).isEqualTo(1)
+            assertThat(secondItemRecomposed).isEqualTo(1)
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = (50).dp, density = rule.density)
+
+        rule.runOnIdle {
+            assertThat(firstItemRecomposed).isEqualTo(1)
+            assertThat(secondItemRecomposed).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun onlyOneMeasurePassForScrollEvent() {
+        val items by mutableStateOf((1..20).toList())
+        lateinit var state: LazyListState
+        rule.setContent {
+            state = rememberLazyListState()
+            LazyRow(Modifier.size(100.dp), state = state) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        val initialMeasurePasses = state.numMeasurePasses
+
+        rule.runOnIdle {
+            with(rule.density) {
+                state.onScroll(-110.dp.toPx())
+            }
+        }
+
+        rule.waitForIdle()
+
+        assertThat(state.numMeasurePasses).isEqualTo(initialMeasurePasses + 1)
+    }
+
+    @Test
+    fun stateUpdatedAfterScroll() {
+        val items by mutableStateOf((1..20).toList())
+        lateinit var state: LazyListState
+        rule.setContent {
+            state = rememberLazyListState()
+            LazyRow(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
+            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 30.dp, density = rule.density)
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(1)
+
+            with(rule.density) {
+                // TODO(b/169232491): test scrolling doesn't appear to be scrolling exactly the right
+                //  number of pixels
+                val expectedOffset = 10.dp.toIntPx()
+                val tolerance = 2.dp.toIntPx()
+                assertThat(state.firstVisibleItemScrollOffset).isEqualTo(expectedOffset, tolerance)
+            }
+        }
+    }
+
+    @Test
+    fun stateUpdatedAfterScrollWithinTheSameItem() {
+        val items by mutableStateOf((1..20).toList())
+        lateinit var state: LazyListState
+        rule.setContent {
+            state = rememberLazyListState()
+            LazyRow(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 10.dp, density = rule.density)
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(0)
+            with(rule.density) {
+                val expectedOffset = 10.dp.toIntPx()
+                val tolerance = 2.dp.toIntPx()
+                assertThat(state.firstVisibleItemScrollOffset)
+                    .isEqualTo(expectedOffset, tolerance)
+            }
+        }
+    }
+
+    @Test
+    fun initialScrollIsApplied() {
+        val items by mutableStateOf((0..20).toList())
+        lateinit var state: LazyListState
+        val expectedOffset = with(rule.density) { 10.dp.toIntPx() }
+        rule.setContent {
+            state = rememberLazyListState(2, expectedOffset)
+            LazyRow(Modifier.size(100.dp).testTag(LazyListTag), state = state) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(state.firstVisibleItemIndex).isEqualTo(2)
+            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(expectedOffset)
+        }
+
+        rule.onNodeWithTag("2")
+            .assertLeftPositionInRootIsEqualTo((-10).dp)
+    }
+
+    @Test
+    fun stateIsRestored() {
+        val restorationTester = StateRestorationTester(rule)
+        val items by mutableStateOf((1..20).toList())
+        var state: LazyListState? = null
+        restorationTester.setContent {
+            state = rememberLazyListState()
+            LazyRow(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state!!
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 30.dp, density = rule.density)
+
+        val (index, scrollOffset) = rule.runOnIdle {
+            state!!.firstVisibleItemIndex to state!!.firstVisibleItemScrollOffset
+        }
+
+        state = null
+
+        restorationTester.emulateSavedInstanceStateRestore()
+
+        rule.runOnIdle {
+            assertThat(state!!.firstVisibleItemIndex).isEqualTo(index)
+            assertThat(state!!.firstVisibleItemScrollOffset).isEqualTo(scrollOffset)
+        }
+    }
+
+    @Test
+    fun snapToItemIndex() {
+        val items by mutableStateOf((1..20).toList())
+        lateinit var state: LazyListState
+        rule.setContent {
+            state = rememberLazyListState()
+            LazyRow(
+                Modifier.size(100.dp).testTag(LazyListTag),
+                state = state
+            ) {
+                items(items) {
+                    Spacer(Modifier.size(20.dp).testTag("$it"))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            runBlocking {
+                state.snapToItemIndex(3, 10)
+            }
+            assertThat(state.firstVisibleItemIndex).isEqualTo(3)
+            assertThat(state.firstVisibleItemScrollOffset).isEqualTo(10)
+        }
+    }
+
+    @Test
+    fun itemsAreNotRedrawnDuringScroll() {
+        val items = (0..20).toList()
+        val redrawCount = Array(6) { 0 }
+        rule.setContent {
+            LazyRow(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(
+                        Modifier.size(20.dp)
+                            .drawBehind { redrawCount[it]++ }
+                    )
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .scrollBy(x = 10.dp, density = rule.density)
+
+        rule.runOnIdle {
+            redrawCount.forEachIndexed { index, i ->
+                Truth.assertWithMessage("Item with index $index was redrawn $i times")
+                    .that(i).isEqualTo(1)
+            }
+        }
+    }
+
+    @Test
+    fun itemInvalidationIsNotCausingAnotherItemToRedraw() {
+        val items = (0..1).toList()
+        val redrawCount = Array(2) { 0 }
+        var stateUsedInDrawScope by mutableStateOf(false)
+        rule.setContent {
+            LazyRow(Modifier.size(100.dp).testTag(LazyListTag)) {
+                items(items) {
+                    Spacer(
+                        Modifier.size(50.dp)
+                            .drawBehind {
+                                redrawCount[it]++
+                                if (it == 1) {
+                                    stateUsedInDrawScope.hashCode()
+                                }
+                            }
+                    )
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            stateUsedInDrawScope = true
+        }
+
+        rule.runOnIdle {
+            Truth.assertWithMessage("First items is not expected to be redrawn")
+                .that(redrawCount[0]).isEqualTo(1)
+            Truth.assertWithMessage("Second items is expected to be redrawn")
+                .that(redrawCount[1]).isEqualTo(2)
+        }
+    }
+
+    @Test
+    fun notVisibleAnymoreItemNotAffectingCrossAxisSize() {
+        val items = (0..1).toList()
+        val itemSize = with(rule.density) { 30.toDp() }
+        val itemSizeMinusOne = with(rule.density) { 29.toDp() }
+        lateinit var state: LazyListState
+        rule.setContent {
+            LazyRow(
+                Modifier.width(itemSizeMinusOne).testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it }
+            ) {
+                items(items) {
+                    Spacer(
+                        if (it == 0) {
+                            Modifier.height(30.dp).width(itemSizeMinusOne)
+                        } else {
+                            Modifier.height(20.dp).width(itemSize)
+                        }
+                    )
+                }
+            }
+        }
+
+        state.scrollBy(itemSize)
+
+        rule.onNodeWithTag(LazyListTag)
+            .assertHeightIsEqualTo(20.dp)
+    }
+
+    @Test
+    fun itemStillVisibleAfterOverscrollIsAffectingCrossAxisSize() {
+        val items = (0..2).toList()
+        val itemSize = with(rule.density) { 30.toDp() }
+        lateinit var state: LazyListState
+        rule.setContent {
+            LazyRow(
+                Modifier.width(itemSize * 1.75f).testTag(LazyListTag),
+                state = rememberLazyListState().also { state = it }
+            ) {
+                items(items) {
+                    Spacer(
+                        if (it == 0) {
+                            Modifier.height(30.dp).width(itemSize / 2)
+                        } else if (it == 1) {
+                            Modifier.height(20.dp).width(itemSize / 2)
+                        } else {
+                            Modifier.height(20.dp).width(itemSize)
+                        }
+                    )
+                }
+            }
+        }
+
+        state.scrollBy(itemSize)
+
+        rule.onNodeWithTag(LazyListTag)
+            .assertHeightIsEqualTo(30.dp)
+    }
+
+    private fun LazyListState.scrollBy(offset: Dp) {
+        runBlocking {
+            smoothScrollBy(with(rule.density) { offset.toIntPx().toFloat() }, snap())
+        }
+    }
+}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollTest.kt
index 8f60ce8c..d216574 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollTest.kt
@@ -90,12 +90,16 @@
     @Composable
     private fun TestContent() {
         if (vertical) {
-            LazyColumnFor(items, Modifier.preferredHeight(300.dp), state) {
-                ItemContent()
+            LazyColumn(Modifier.preferredHeight(300.dp), state) {
+                items(items) {
+                    ItemContent()
+                }
             }
         } else {
-            LazyRowFor(items, Modifier.preferredWidth(300.dp), state) {
-                ItemContent()
+            LazyRow(Modifier.preferredWidth(300.dp), state) {
+                items(items) {
+                    ItemContent()
+                }
             }
         }
     }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt
index c30a7c6..aee281c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt
@@ -478,7 +478,7 @@
     if (isVertical) {
         check(maxHeight != Constraints.Infinity) {
             "Nesting scrollable in the same direction layouts like ScrollableContainer and " +
-                "LazyColumnFor is not allowed. If you want to add a header before the list of" +
+                "LazyColumn is not allowed. If you want to add a header before the list of" +
                 " items please take a look on LazyColumn component which has a DSL api which" +
                 " allows to first add a header via item() function and then the list of " +
                 "items via items()."
@@ -486,7 +486,7 @@
     } else {
         check(maxWidth != Constraints.Infinity) {
             "Nesting scrollable in the same direction layouts like ScrollableRow and " +
-                "LazyRowFor is not allowed. If you want to add a header before the list of " +
+                "LazyRow is not allowed. If you want to add a header before the list of " +
                 "items please take a look on LazyRow component which has a DSL api which " +
                 "allows to first add a fixed element via item() function and then the " +
                 "list of items via items()."
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyFor.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyFor.kt
index 2986425..89b9186 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyFor.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyFor.kt
@@ -31,8 +31,6 @@
  * See [LazyColumnForIndexed] if you need to have both item and index params in [itemContent].
  * See [LazyRowFor] if you are looking for a horizontally scrolling version.
  *
- * @sample androidx.compose.foundation.samples.LazyColumnForSample
- *
  * @param items the backing list of data to display
  * @param modifier the modifier to apply to this layout
  * @param state the state object to be used to control or observe the list's state
@@ -55,6 +53,14 @@
  */
 @OptIn(InternalLayoutApi::class)
 @Composable
+@Deprecated(
+    "Use LazyColumn instead",
+    ReplaceWith(
+        "LazyColumn(modifier, state, contentPadding, horizontalAlignment = " +
+            "horizontalAlignment) { \n items(items, itemContent) \n }",
+        "androidx.compose.foundation.lazy.LazyColumn"
+    )
+)
 fun <T> LazyColumnFor(
     items: List<T>,
     modifier: Modifier = Modifier,
@@ -86,8 +92,6 @@
  *
  * See [LazyRowForIndexed] if you are looking for a horizontally scrolling version.
  *
- * @sample androidx.compose.foundation.samples.LazyColumnForIndexedSample
- *
  * @param items the backing list of data to display
  * @param modifier the modifier to apply to this layout
  * @param state the state object to be used to control or observe the list's state
@@ -111,6 +115,14 @@
  */
 @OptIn(InternalLayoutApi::class)
 @Composable
+@Deprecated(
+    "Use LazyColumn instead",
+    ReplaceWith(
+        "LazyColumn(modifier, state, contentPadding, horizontalAlignment = " +
+            "horizontalAlignment) { \n itemsIndexed(items, itemContent) \n }",
+        "androidx.compose.foundation.lazy.LazyColumn"
+    )
+)
 fun <T> LazyColumnForIndexed(
     items: List<T>,
     modifier: Modifier = Modifier,
@@ -140,8 +152,6 @@
  * See [LazyRowForIndexed] if you need to have both item and index params in [itemContent].
  * See [LazyColumnFor] if you are looking for a vertically scrolling version.
  *
- * @sample androidx.compose.foundation.samples.LazyRowForSample
- *
  * @param items the backing list of data to display.
  * @param modifier the modifier to apply to this layout.
  * @param state the state object to be used to control or observe the list's state.
@@ -164,6 +174,14 @@
  */
 @OptIn(InternalLayoutApi::class)
 @Composable
+@Deprecated(
+    "Use LazyRow instead",
+    ReplaceWith(
+        "LazyRow(modifier, state, contentPadding, verticalAlignment = " +
+            "verticalAlignment) { \n items(items, itemContent) \n }",
+        "androidx.compose.foundation.lazy.LazyColumn"
+    )
+)
 fun <T> LazyRowFor(
     items: List<T>,
     modifier: Modifier = Modifier,
@@ -194,8 +212,6 @@
  *
  * See [LazyColumnForIndexed] if you are looking for a vertically scrolling version.
  *
- * @sample androidx.compose.foundation.samples.LazyRowForIndexedSample
- *
  * @param items the backing list of data to display.
  * @param modifier the modifier to apply to this layout.
  * @param state the state object to be used to control or observe the list's state.
@@ -219,6 +235,14 @@
  */
 @OptIn(InternalLayoutApi::class)
 @Composable
+@Deprecated(
+    "Use LazyRow instead",
+    ReplaceWith(
+        "LazyRow(modifier, state, contentPadding, verticalAlignment = " +
+            "verticalAlignment) { \n itemsIndexed(items, itemContent) \n }",
+        "androidx.compose.foundation.lazy.LazyColumn"
+    )
+)
 fun <T> LazyRowForIndexed(
     items: List<T>,
     modifier: Modifier = Modifier,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyGrid.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyGrid.kt
index eb74118..2bcbed5 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyGrid.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyGrid.kt
@@ -29,7 +29,7 @@
 
 /**
  * The DSL implementation of a lazy grid layout. It composes only visible rows of the grid.
- * This API is not stable, please consider using stable components like [LazyColumnFor] and [Row]
+ * This API is not stable, please consider using stable components like [LazyColumn] and [Row]
  * to achieve the same result.
  *
  * @param columns a fixed number of columns of the grid
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt
index 96e0375..0384857 100644
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt
+++ b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt
@@ -88,7 +88,7 @@
 
 /**
  * Vertical scrollbar that can be attached to some scrollable
- * component (ScrollableColumn, LazyColumnFor) and share common state with it.
+ * component (ScrollableColumn, LazyColumn) and share common state with it.
  *
  * Can be placed independently.
  *
@@ -128,7 +128,7 @@
 
 /**
  * Horizontal scrollbar that can be attached to some scrollable
- * component (ScrollableRow, LazyRowFor) and share common state with it.
+ * component (ScrollableRow, LazyRow) and share common state with it.
  *
  * Can be placed independently.
  *
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
index d2ed8a5..c2f7983 100644
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
+++ b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
@@ -22,7 +22,7 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.lazy.LazyColumnFor
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.LazyListState
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.Composable
@@ -436,12 +436,13 @@
         scrollbarWidth: Dp,
     ) = withTestEnvironment {
         Box(Modifier.size(size)) {
-            LazyColumnFor(
-                (0 until childCount).toList(),
+            LazyColumn(
                 Modifier.fillMaxSize().testTag("column"),
                 state
             ) {
-                Box(Modifier.size(childSize).testTag("box$it"))
+                items((0 until childCount).toList()) {
+                    Box(Modifier.size(childSize).testTag("box$it"))
+                }
             }
 
             VerticalScrollbar(
diff --git a/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/lazy/LazyListScrollingBenchmark.kt b/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/lazy/LazyListScrollingBenchmark.kt
index 4c14493..8e652ac 100644
--- a/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/lazy/LazyListScrollingBenchmark.kt
+++ b/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/lazy/LazyListScrollingBenchmark.kt
@@ -24,11 +24,7 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.LazyColumnFor
-import androidx.compose.foundation.lazy.LazyColumnForIndexed
 import androidx.compose.foundation.lazy.LazyRow
-import androidx.compose.foundation.lazy.LazyRowFor
-import androidx.compose.foundation.lazy.LazyRowForIndexed
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.emptyContent
@@ -92,13 +88,9 @@
                 LazyColumnWithItemAndItems,
                 LazyColumnWithItems,
                 LazyColumnWithItemsIndexed,
-                LazyColumnFor,
-                LazyColumnForIndexed,
                 LazyRowWithItemAndItems,
                 LazyRowWithItems,
-                LazyRowWithItemsIndexed,
-                LazyRowFor,
-                LazyRowForIndexed
+                LazyRowWithItemsIndexed
             )
     }
 }
@@ -147,26 +139,6 @@
     }
 }
 
-private val LazyColumnFor = LazyListScrollingTestCase("LazyColumnFor") {
-    LazyColumnFor(items, modifier = Modifier.height(400.dp).fillMaxWidth()) {
-        if (it.index == 0) {
-            RemeasurableItem()
-        } else {
-            RegularItem()
-        }
-    }
-}
-
-private val LazyColumnForIndexed = LazyListScrollingTestCase("LazyColumnForIndexed") {
-    LazyColumnForIndexed(items, modifier = Modifier.height(400.dp).fillMaxWidth()) { index, _ ->
-        if (index == 0) {
-            RemeasurableItem()
-        } else {
-            RegularItem()
-        }
-    }
-}
-
 private val LazyRowWithItemAndItems = LazyListScrollingTestCase("LazyRowWithItemAndItems") {
     LazyRow(modifier = Modifier.width(400.dp).fillMaxHeight()) {
         item {
@@ -202,26 +174,6 @@
     }
 }
 
-private val LazyRowFor = LazyListScrollingTestCase("LazyRowFor") {
-    LazyRowFor(items, modifier = Modifier.width(400.dp).fillMaxHeight()) {
-        if (it.index == 0) {
-            RemeasurableItem()
-        } else {
-            RegularItem()
-        }
-    }
-}
-
-private val LazyRowForIndexed = LazyListScrollingTestCase("LazyRowForIndexed") {
-    LazyRowForIndexed(items, modifier = Modifier.width(400.dp).fillMaxHeight()) { index, _ ->
-        if (index == 0) {
-            RemeasurableItem()
-        } else {
-            RegularItem()
-        }
-    }
-}
-
 // TODO(b/169852102 use existing public constructs instead)
 private fun ComposeBenchmarkRule.toggleStateBenchmarkMeasure(
     caseFactory: () -> ListRemeasureTestCase
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/Layout.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/Layout.kt
index dcab8ad..07e9583 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/Layout.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/layout/Layout.kt
@@ -29,7 +29,7 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.lazy.LazyColumnFor
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.material.Button
 import androidx.compose.material.Scaffold
 import androidx.compose.material.Surface
@@ -137,8 +137,10 @@
         onSelected: (Artist) -> Unit
     ) {
         Surface(Modifier.fillMaxSize()) {
-            LazyColumnFor(feedItems) { item ->
-                ArtistCard(item, onSelected)
+            LazyColumn {
+                items(feedItems) { item ->
+                    ArtistCard(item, onSelected)
+                }
             }
         }
     }
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/mentalmodel/MentalModel.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/mentalmodel/MentalModel.kt
index e110e4d..635fbdf 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/mentalmodel/MentalModel.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/mentalmodel/MentalModel.kt
@@ -23,7 +23,7 @@
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.lazy.LazyColumnFor
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.material.Button
 import androidx.compose.material.Checkbox
 import androidx.compose.material.Divider
@@ -118,12 +118,14 @@
             Text(header, style = MaterialTheme.typography.h5)
             Divider()
 
-            // LazyColumnFor is the Compose version of a RecyclerView.
-            // The lambda passed is similar to a RecyclerView.ViewHolder.
-            LazyColumnFor(names) { name ->
-                // When an item's [name] updates, the adapter for that item
-                // will recompose. This will not recompose when [header] changes
-                NamePickerItem(name, onNameClicked)
+            // LazyColumn is the Compose version of a RecyclerView.
+            // The lambda passed to items() is similar to a RecyclerView.ViewHolder.
+            LazyColumn {
+                items(names) { name ->
+                    // When an item's [name] updates, the adapter for that item
+                    // will recompose. This will not recompose when [header] changes
+                    NamePickerItem(name, onNameClicked)
+                }
             }
         }
     }
diff --git a/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/LazyColumnActivity.kt b/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/LazyColumnActivity.kt
index 8fa8f88..d981bab 100644
--- a/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/LazyColumnActivity.kt
+++ b/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/LazyColumnActivity.kt
@@ -22,7 +22,7 @@
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.lazy.LazyColumnFor
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.material.Card
 import androidx.compose.material.Checkbox
 import androidx.compose.material.Text
@@ -38,13 +38,11 @@
         val itemCount = intent.getIntExtra(EXTRA_ITEM_COUNT, 1000)
 
         setContent {
-            LazyColumnFor(
-                items = List(itemCount) {
-                    Entry("Item $it")
-                },
-                modifier = Modifier.fillMaxWidth(),
-                itemContent = { ListRow(it) }
-            )
+            LazyColumn(modifier = Modifier.fillMaxWidth()) {
+                items(List(itemCount) { Entry("Item $it") }) {
+                    ListRow(it)
+                }
+            }
         }
     }
 
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BackdropScaffoldSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BackdropScaffoldSamples.kt
index b2a34de..0294cad 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BackdropScaffoldSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BackdropScaffoldSamples.kt
@@ -19,7 +19,6 @@
 import androidx.annotation.Sampled
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.LazyColumnFor
 import androidx.compose.material.BackdropScaffold
 import androidx.compose.material.BackdropValue
 import androidx.compose.material.ExperimentalMaterialApi
@@ -86,14 +85,16 @@
             )
         },
         backLayerContent = {
-            LazyColumnFor((1..5).toList()) {
-                ListItem(
-                    Modifier.clickable {
-                        selection.value = it
-                        scaffoldState.conceal()
-                    },
-                    text = { Text("Select $it") }
-                )
+            LazyColumn {
+                for (i in 1..5) item {
+                    ListItem(
+                        Modifier.clickable {
+                            selection.value = i
+                            scaffoldState.conceal()
+                        },
+                        text = { Text("Select $i") }
+                    )
+                }
             }
         },
         frontLayerContent = {
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt
index cfa1849..ca1b39d 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt
@@ -22,7 +22,7 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.lazy.LazyColumnFor
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.material.Card
 import androidx.compose.material.DismissDirection.EndToStart
 import androidx.compose.material.DismissDirection.StartToEnd
@@ -78,57 +78,63 @@
     // will animate to red if you're swiping left or green if you're swiping right. When you let
     // go, the item will animate out of the way if you're swiping left (like deleting an email) or
     // back to its default position if you're swiping right (like marking an email as read/unread).
-    LazyColumnFor(items) { item ->
-        var unread by remember { mutableStateOf(false) }
-        val dismissState = rememberDismissState(
-            confirmStateChange = {
-                if (it == DismissedToEnd) unread = !unread
-                it != DismissedToEnd
-            }
-        )
-        SwipeToDismiss(
-            state = dismissState,
-            modifier = Modifier.padding(vertical = 4.dp),
-            directions = setOf(StartToEnd, EndToStart),
-            dismissThresholds = { direction ->
-                FractionalThreshold(if (direction == StartToEnd) 0.25f else 0.5f)
-            },
-            background = {
-                val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
-                val color = animate(
-                    when (dismissState.targetValue) {
-                        Default -> Color.LightGray
-                        DismissedToEnd -> Color.Green
-                        DismissedToStart -> Color.Red
-                    }
-                )
-                val alignment = when (direction) {
-                    StartToEnd -> Alignment.CenterStart
-                    EndToStart -> Alignment.CenterEnd
+    LazyColumn {
+        items(items) { item ->
+            var unread by remember { mutableStateOf(false) }
+            val dismissState = rememberDismissState(
+                confirmStateChange = {
+                    if (it == DismissedToEnd) unread = !unread
+                    it != DismissedToEnd
                 }
-                val icon = when (direction) {
-                    StartToEnd -> Icons.Default.Done
-                    EndToStart -> Icons.Default.Delete
-                }
-                val scale = animate(if (dismissState.targetValue == Default) 0.75f else 1f)
-
-                Box(
-                    modifier = Modifier.fillMaxSize().background(color).padding(horizontal = 20.dp),
-                    contentAlignment = alignment
-                ) {
-                    Icon(icon, Modifier.scale(scale))
-                }
-            },
-            dismissContent = {
-                Card(
-                    elevation = animate(if (dismissState.dismissDirection != null) 4.dp else 0.dp)
-                ) {
-                    ListItem(
-                        text = { Text(item, fontWeight = if (unread) FontWeight.Bold else null) },
-                        secondaryText = { Text("Swipe me left or right!") }
+            )
+            SwipeToDismiss(
+                state = dismissState,
+                modifier = Modifier.padding(vertical = 4.dp),
+                directions = setOf(StartToEnd, EndToStart),
+                dismissThresholds = { direction ->
+                    FractionalThreshold(if (direction == StartToEnd) 0.25f else 0.5f)
+                },
+                background = {
+                    val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
+                    val color = animate(
+                        when (dismissState.targetValue) {
+                            Default -> Color.LightGray
+                            DismissedToEnd -> Color.Green
+                            DismissedToStart -> Color.Red
+                        }
                     )
+                    val alignment = when (direction) {
+                        StartToEnd -> Alignment.CenterStart
+                        EndToStart -> Alignment.CenterEnd
+                    }
+                    val icon = when (direction) {
+                        StartToEnd -> Icons.Default.Done
+                        EndToStart -> Icons.Default.Delete
+                    }
+                    val scale = animate(if (dismissState.targetValue == Default) 0.75f else 1f)
+
+                    Box(
+                        Modifier.fillMaxSize().background(color).padding(horizontal = 20.dp),
+                        contentAlignment = alignment
+                    ) {
+                        Icon(icon, Modifier.scale(scale))
+                    }
+                },
+                dismissContent = {
+                    Card(
+                        elevation = animate(
+                            if (dismissState.dismissDirection != null) 4.dp else 0.dp
+                        )
+                    ) {
+                        ListItem(
+                            text = {
+                                Text(item, fontWeight = if (unread) FontWeight.Bold else null)
+                            },
+                            secondaryText = { Text("Swipe me left or right!") }
+                        )
+                    }
                 }
-            }
-        )
+            )
+        }
     }
 }
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/PointerInputDuringSubCompDemo.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/PointerInputDuringSubCompDemo.kt
index f6ea061..8901b03 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/PointerInputDuringSubCompDemo.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/PointerInputDuringSubCompDemo.kt
@@ -23,7 +23,7 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.foundation.lazy.LazyColumnFor
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
@@ -60,27 +60,28 @@
                 "it is actually a new item that has not been hit tested yet.  If you keep " +
                 "your finger there and then add more fingers, it will track those new fingers."
         )
-        LazyColumnFor(
-            List(100) { index -> index },
+        LazyColumn(
             Modifier
                 .fillMaxSize()
                 .wrapContentSize(Alignment.Center)
                 .size(200.dp)
                 .background(color = Color.White)
         ) {
-            val pointerCount = remember { mutableStateOf(0) }
+            items(List(100) { index -> index }) {
+                val pointerCount = remember { mutableStateOf(0) }
 
-            Box(
-                Modifier.fillParentMaxSize()
-                    .border(width = 1.dp, color = Color.Black)
-                    .pointerCounterGestureFilter { newCount -> pointerCount.value = newCount },
-                contentAlignment = Alignment.Center
-            ) {
-                Text(
-                    "${pointerCount.value}",
-                    fontSize = TextUnit.Em(16),
-                    color = Color.Black
-                )
+                Box(
+                    Modifier.fillParentMaxSize()
+                        .border(width = 1.dp, color = Color.Black)
+                        .pointerCounterGestureFilter { newCount -> pointerCount.value = newCount },
+                    contentAlignment = Alignment.Center
+                ) {
+                    Text(
+                        "${pointerCount.value}",
+                        fontSize = TextUnit.Em(16),
+                        color = Color.Black
+                    )
+                }
             }
         }
     }
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/NestedScrollSamples.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/NestedScrollSamples.kt
index 6b4dccc..4a95ba4 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/NestedScrollSamples.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/NestedScrollSamples.kt
@@ -23,7 +23,6 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.LazyColumnFor
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
@@ -134,11 +133,13 @@
                     .nestedScroll(connection, dispatcher = nestedScrollDispatcher)
             ) {
                 // hypothetical scrollable child which we will listen in connection above
-                LazyColumnFor(listOf(1, 2, 3, 4, 5)) {
-                    Text(
-                        "Magenta text above will change first when you scroll me",
-                        modifier = Modifier.padding(5.dp)
-                    )
+                LazyColumn {
+                    items(listOf(1, 2, 3, 4, 5)) {
+                        Text(
+                            "Magenta text above will change first when you scroll me",
+                            modifier = Modifier.padding(5.dp)
+                        )
+                    }
                 }
                 // simply show our value. It will change when we scroll child list above, taking
                 // child's scroll delta until we reach maxValue or minValue
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
index cc7f3c6..7f0aca2 100644
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
@@ -29,7 +29,7 @@
 import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.lazy.LazyColumnFor
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.runtime.ExperimentalComposeApi
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -288,10 +288,12 @@
         var height by mutableStateOf(10.dp)
         setContent {
             Box(Modifier.padding(10.dp)) {
-                LazyColumnFor(
-                    listOf(Color.Red, Color.Green, Color.Blue, Color.Black, Color.Gray)
-                ) { color ->
-                    Box(Modifier.size(width = 30.dp, height = height).background(color))
+                LazyColumn {
+                    items(
+                        listOf(Color.Red, Color.Green, Color.Blue, Color.Black, Color.Gray)
+                    ) { color ->
+                        Box(Modifier.size(width = 30.dp, height = height).background(color))
+                    }
                 }
             }
         }