ScrollView Fundamentals

A View never scrolls; taller content is cut off. ScrollView wraps its children in a scrollable container (a ScrollView on Android, a UIScrollView on iOS). It needs a bounded height, so give it flex: 1 inside a parent that has one; a missing flex: 1 up the tree is the usual cause of a list that will not scroll. Style the content with contentContainerStyle, since padding and gap belong to the inner container.

src/demos/CatalogScroll.tsx: a a sticky header over twelve cards (excerpt)TSX
      <ScrollView ref={scroller} contentContainerStyle={ui.screen} stickyHeaderIndices={[0]}
        keyboardDismissMode="on-drag">
        <Text style={[ui.h1, { backgroundColor: '#eceff1' }]}>Catalog</Text>
        {[...books, ...books].map((b, i) => (
          <Text key={i} style={[ui.card, { height: 120 }]}>{b.title}{'\n'}{b.summary}</Text>
        ))}
      </ScrollView>

stickyHeaderIndices={[0]} pins the first child while the rest scroll under it. The ref (useRef<ScrollView>(null)) gives you scrollTo({ x, y, animated }), scrollToEnd() and flashScrollIndicators(). Two props control the keyboard: keyboardDismissMode ('none', 'on-drag', or 'interactive' on iOS) and keyboardShouldPersistTaps. The latter defaults to 'never', so the first tap outside a focused field only closes the keyboard; set it to 'handled' whenever a scrolling form has buttons, or users must tap Save twice.