Skip to main content

ScrollView

Unlike the web, Views in native don't scroll by default. Even if we add so many items they're longer than the screen, they will just disappear off the screen. To make a page scrollable, we need to use a different component: a ScrollView.

Replace the containing View with a ScrollView

Update: app/index.tsx
-import { StyleSheet, TextInput, View } from "react-native";
+import { StyleSheet, TextInput, View, ScrollView } from "react-native";
import { theme } from "../theme";
import { ShoppingListItem } from "../components/ShoppingListItem";
import { useState } from "react";
@@ -30,7 +30,7 @@ export default function App() {
};

return (
- <View style={styles.container}>
+ <ScrollView style={styles.container}>
<TextInput
value={value}
style={styles.textInput}
@@ -42,7 +42,7 @@ export default function App() {
{shoppingList.map((item) => (
<ShoppingListItem name={item.name} key={item.id} />
))}
- </View>
+ </ScrollView>
);
}

Use contentContainerStyle for padding

Let's try adding so many items they don't all fit the screen. You'll notice that we can scroll down to see all of them, but the bottom of the last item still gets cut off. This is actually due to the paddingTop we added to the container style to give some space to the header. The scrollable elements style prop should not contain any margins or paddings. Instead we should pass these in with the contentContainer prop.

Update: app/index.tsx
@@ -30,7 +30,10 @@ export default function App() {
};

return (
- <ScrollView style={styles.container}>
+ <ScrollView
+ style={styles.container}
+ contentContainerStyle={styles.contentContainer}
+ >
<TextInput
value={value}
style={styles.textInput}
@@ -49,9 +52,11 @@ export default function App() {
const styles = StyleSheet.create({
container: {
backgroundColor: theme.colorWhite,
- paddingTop: 12,
flex: 1,
},
+ contentContainer: {
+ paddingVertical: 12,
+ },
textInput: {
borderColor: theme.colorLightGrey,
borderWidth: 2,

Make the search bar sticky

Currently our text input disappears when we scroll down. One way to make it sticky is using stickyHeaderIndices which allows us to make a specific element sticky.

Let's also set the text input background to white and update the padding so that it won't move at all with the rest of the ScrollView.

Update: app/index.tsx
@@ -33,6 +33,7 @@ export default function App() {
<ScrollView
style={styles.container}
contentContainerStyle={styles.contentContainer}
+ stickyHeaderIndices={[0]}
>
<TextInput
value={value}
@@ -53,9 +54,10 @@ const styles = StyleSheet.create({
container: {
backgroundColor: theme.colorWhite,
flex: 1,
+ paddingTop: 12,
},
contentContainer: {
- paddingVertical: 12,
+ paddingBottom: 24,
},
textInput: {
borderColor: theme.colorLightGrey,
@@ -65,5 +67,6 @@ const styles = StyleSheet.create({
borderRadius: 50,
marginHorizontal: 12,
marginBottom: 12,
+ backgroundColor: theme.colorWhite,
},
});

Checkpoint

Checkpoint