Building Cross-Platform Apps

Lesson 4 of 15

Navigation patterns

Multi-screen apps need navigation — and on mobile, navigation is platform-flavoured: iOS and Android users expect different behaviours (back gestures, headers, transitions). Cross-platform navigation means using one library (React Navigation) that renders each platform's conventions while you write the structure once. This lesson covers the standard patterns — stack, tabs, drawer, modals — and how to pick them so the app feels native on both. Let's navigate the cross-platform way. Let's structure screens for both platforms.

The navigator types — one library, native feel

REACT NAVIGATION — the standard cross-platform navigation library. You compose
NAVIGATORS; each renders the RIGHT native behaviour per platform:STACK — push/pop screens (list -> detail). Gives a native header + the platform
        back behaviour: iOS swipe-back gesture, Android hardware/gesture back.
  <Stack.Navigator>
    <Stack.Screen name="Feed" component={FeedScreen} />
    <Stack.Screen name="Post" component={PostScreen} />
  </Stack.Navigator>TABS — bottom tab bar for 3-5 top-level sections (thumb-reachable, always visible).
  <Tab.Navigator> <Tab.Screen ... /> ... </Tab.Navigator>DRAWER — a slide-in side menu for many/secondary destinations.MODAL — a screen presented modally (slides up) for focused tasks (create/edit).THE STANDARD STRUCTURE: TABS at the top level, a STACK inside each tab (so each
section drills into detail), plus MODALS for tasks. Fits almost every app.

Cross-platform navigation uses one library — React Navigation — and you compose navigators, each of which renders the right native behaviour per platform. The stack pushes and pops screens (list → detail) and gives a native header plus the platform back behaviour — the iOS swipe-back gesture and the Android hardware/gesture backfor free. Tabs put 3–5 top-level sections in a bottom bar (thumb-reachable, always visible). A drawer is a slide-in side menu for many or secondary destinations. A modal presents a screen modally (slides up) for focused tasks (create/edit). The standard structure — which fits almost every app — is tabs at the top level, a stack inside each tab (so each section can drill into detail), plus modals for tasks. The payoff is that you describe this structure once and it feels native on both platforms, because the library maps it to each platform's transitions, headers, and gestures.

Moving between screens + platform conventions

NAVIGATING — each screen gets a "navigation" prop:
  navigation.navigate('Post', { id: 42 });   // push + pass params
  navigation.goBack();                        // pop (also: iOS swipe / Android back)
  // read params in the target:  route.params.idPLATFORM CONVENTIONS THE LIBRARY HANDLES (or you should respect):- BACK: iOS shows a back chevron + supports the swipe-from-left gesture; Android
  uses the hardware/gesture BACK button. React Navigation wires BOTH — don't break
  them (always allow going back; never a dead end).- HEADERS/TRANSITIONS: native-stack uses each platform's real navigation
  animations + header style. It looks like iOS on iOS, Android on Android.- TABS: bottom tabs are standard on both; a top tab bar is more Android-flavoured.
  Match the platform's norm where it matters.- Handle the ANDROID hardware back button in modals/flows (React Navigation does
  by default; custom flows may need attention).AUTH FLOW: a root navigator switches between the auth stack (logged out) and the
main tabs (logged in) — conditionally render based on auth state.

You move between screens with the navigation prop: navigation.navigate('Post', { id: 42 }) pushes a screen and passes params, the target reads them via route.params, and navigation.goBack() pops. Crucially, React Navigation wires the platform back conventions for you: iOS gets a back chevron and the swipe-from-left gesture; Android gets the hardware/gesture back button — so never break "back" and never leave a dead end. The native-stack navigator uses each platform's real transitions and header style, so the app looks like iOS on iOS and Android on Android from the same code. Match platform norms where they matter — bottom tabs are standard on both, while a top tab bar reads as more Android. Handle the Android hardware back button in custom flows (the library does by default). And structure the auth flow with a root navigator that conditionally shows the auth stack (logged out) or the main tabs (logged in). Describe it once; get native-feeling navigation on both.

The mistake beginners make

The first mistake is breaking the platform back behaviour — building custom navigation that ignores the iOS swipe-back or the Android hardware back button, which feels broken to users of that platform; use React Navigation and always support going back. The second mistake is ignoring platform conventions — forcing an iOS-style pattern onto Android (or vice-versa) so the app feels foreign on one platform; use the native-stack and platform-appropriate patterns (bottom tabs, real transitions). The third mistake is wrong pattern for the structure — cramming everything into a stack, or putting too many tabs (6+) in the bottom bar; match tabs to sections, stacks to detail, modals to tasks, and keep to 3–5 tabs. And not handling the auth flow — showing the main app when logged out; switch navigators on auth state. Use React Navigation, respect platform back + conventions, match patterns to structure, and handle auth.

Your turn


Your turn

  1. Build the standard structure: set up React Navigation with bottom tabs at the top level and a stack inside each tab (e.g. FeedStack: list -> detail), so each section can drill into detail while staying in its tab.
  2. Navigate with params: from a list, call navigation.navigate('Detail', { id }) to push a detail screen and read route.params.id in it; use navigation.goBack() to pop.
  3. Respect platform back: rely on the native-stack so iOS gets the swipe-back gesture + chevron and Android gets the hardware/gesture back — confirm you can always get back (no dead ends).
  4. Add a modal for a task: present a create/edit screen modally (slides up over everything) rather than pushing it awkwardly onto the stack.
  5. Handle auth: use a root navigator that conditionally shows an auth stack (logged out) vs the main tabs (logged in), switching on auth state.

Key points

  • Cross-platform navigation uses ONE library — React Navigation — and you compose navigators (stack, tabs, drawer, modal); each renders the RIGHT native behaviour per platform (iOS transitions/gestures vs Android), so you write the structure once and it feels native on both.
  • Stack = push/pop (list -> detail) with a native header + platform back (iOS swipe-back + chevron, Android hardware/gesture back); Tabs = 3-5 top-level sections in a bottom bar; Drawer = side menu; Modal = focused tasks (slides up).
  • The standard structure fits almost every app: TABS at the top level, a STACK inside each tab (drill into detail), plus MODALS for tasks; navigate with navigation.navigate('Screen', params) + route.params, and navigation.goBack() to pop.
  • Respect platform conventions the library wires for you: never break the iOS swipe-back or Android hardware back (always allow going back, no dead ends); use native-stack for real per-platform transitions/headers; handle the auth flow with a root navigator switching on auth state.
  • The mistakes: breaking platform back behaviour (feels broken), ignoring platform conventions (feels foreign on one platform), wrong pattern for the structure (everything in a stack / too many tabs — match tabs=sections, stacks=detail, modals=tasks, 3-5 tabs), and not handling auth.

Q&A · 0

Enrol to ask questions and join the discussion.

No questions yet — be the first to ask.