Supporting iPad Split View and Multitasking Layouts
AI generated
RN
native
React Native / iPadOS
Supporting iPad Split View and Multitasking Layouts
How layouts respond to changing window sizes instead of breaking on every multitasking mode

An iPad screen has long stopped being a guaranteed, fixed full screen space for an app, and can shrink to a fraction of its original width at any moment through Split View, Slide Over or Stage Manager, without the app ever restarting. Anyone who bakes fixed pixel widths or an assumed screen orientation into their components will eventually see clipped content or overlapping elements. This article covers how React Native apps respond to these window size changes, which responsive layout strategies replace fixed full screen assumptions, and how to practically test the different multitasking states.

11 min read iPadOS Split View Responsive Layout

1. Overview of iPadOS multitasking modes

iPadOS has several distinct multitasking states that fundamentally differ for an app: in the classic full screen mode, the app takes up the entire available screen area, while Split View divides the screen between two apps, allowing window widths ranging from roughly a third up to half the screen depending on the chosen split. Slide Over places a third app as a floating, smaller window on top of the other two, which suddenly renders an app in a noticeably narrower, vertically oriented window, regardless of the iPad's actual physical orientation.

Stage Manager, available on newer iPad models, further extends this concept with freely resizable, overlapping windows whose size the user can change at will by dragging a window's corner, similar to a desktop operating system. For a React Native app, this whole catalog of modes means the available screen area at runtime can never be treated as a fixed constant, but as a value that can change at any moment while the app is already running.

2. How an app learns about window size changes

The useWindowDimensions hook from React Native core returns the current width and height of the window available to the app and automatically triggers a re-render of the calling component whenever those values change, for example because the user drags the divider between two apps in Split View. Unlike the static Dimensions.get('window') API, which only returns the value once at the time it is called, useWindowDimensions continuously reacts to every change, making it the preferred choice for any component whose layout depends on the actual window size.

For cases where a window size change needs handling outside the React render cycle, such as triggering a native animation, the Dimensions API additionally provides an addEventListener for the change event, letting the same change be handled imperatively as well. In most cases, though, the declarative useWindowDimensions hook is fully sufficient, since React already handles re-renders on state changes anyway.


import { useWindowDimensions, View } from 'react-native';

function ProductLayout() {
  const { width } = useWindowDimensions();
  const isCompact = width < 600;

  return (
    <View style={{ flexDirection: isCompact ? 'column' : 'row' }}>
      <ProductList compact={isCompact} />
      <ProductDetail visible={!isCompact} />
    </View>
  );
}

3. Identifying fixed full screen assumptions in existing code

The most reliable way to spot hidden full screen assumptions in an existing codebase is a targeted search for Dimensions.get('window') as well as hardcoded pixel values in style definitions that clearly assume the full iPad width, such as width: 1024 or a fixed column count in a grid that ignores the possibility of being shrunk. Layouts that read the window width once at component mount time and store the result in local state without reacting to later changes are particularly commonly affected.

A second, less obvious source of bugs lies in conditions that determine tablet specific behavior purely based on the device itself rather than on the actually available window width, such as a check like Platform.isPad, which still returns true even while the app runs in a narrow Slide Over window. For reliable behavior, the actual width through useWindowDimensions, not the device class itself, should drive layout decisions.

4. Responsive layout strategies instead of fixed full screen assumptions

Instead of using fixed pixel values in style objects, a layout should consistently build on flexbox properties such as flex, flexWrap and minWidth, which behave proportionally regardless of the actually available width and therefore automatically grow or shrink with the window. For structural decisions that cannot be solved purely through flexbox, such as whether a two column view even makes sense or should switch to a single column display, clearly defined breakpoints that react to the same value returned by useWindowDimensions work well.

A central useBreakpoint hook has proven useful in practice, translating the current window width into named categories such as compact, regular and expanded, similar to the size class concept from UIKit, instead of defining separate, possibly inconsistent width thresholds inside every individual component. This shared hook ensures every component in the app aligns with the same thresholds and shows consistent rather than fragmented layout behavior when switching between Split View and full screen.


import { useWindowDimensions } from 'react-native';

type Breakpoint = 'compact' | 'regular' | 'expanded';

function useBreakpoint(): Breakpoint {
  const { width } = useWindowDimensions();
  if (width < 600) return 'compact';
  if (width < 900) return 'regular';
  return 'expanded';
}

function CatalogScreen() {
  const breakpoint = useBreakpoint();
  const columns = breakpoint === 'compact' ? 1 : breakpoint === 'regular' ? 2 : 3;

  return <ProductGrid columns={columns} />;
}

5. Safe area behavior alongside multitasking

react-native-safe-area-context returns the current safe area insets, meaning the distance to the notch, the home indicator and rounded corners, and those values can differ between Split View or Slide Over mode and full screen mode, because the app's area shifts relative position within the physical screen. An app sitting in Slide Over as a narrow, centered window over another app, for instance, has different effective margins than the same app running full screen, even though the physical device stays identical.

SafeAreaProvider from react-native-safe-area-context automatically reacts to these changes and updates the values returned through useSafeAreaInsets whenever the multitasking state changes, so a component that reads its insets correctly through the hook rather than through assumed fixed values stays automatically correct in every multitasking state, without needing any extra code to detect which mode is currently active.

6. Info.plist configuration for multitasking support

For an iPad app to support Split View and Slide Over at all, the UIRequiresFullScreen key in Info.plist must either be absent or explicitly set to false, because its absence in older, template generated projects can still default to true in some cases and permanently excludes the app from the multitasking pool. Every supported interface orientation for both iPhone and iPad must also be correctly declared under UISupportedInterfaceOrientations~ipad, since multitasking windows on iPad can appear in either axis regardless of the device's physical orientation.

For Expo projects, this configuration can be controlled directly through the ios.requireFullScreen key in app.json without manually editing the native Info.plist, where the value deliberately needs to be set to false, since Expo enables a more conservative full screen mode by default in newly generated projects, one that effectively disables multitasking even if the rest of the code is already fully built responsively.


{
  "expo": {
    "ios": {
      "requireFullScreen": false,
      "supportsTablet": true
    }
  }
}

7. Stage Manager: freely resizable windows as a further step

Stage Manager extends the classic Split View and Slide Over modes with windows that can be freely resized by dragging, no longer limited to a handful of fixed ratios but able to vary continuously between a minimum and the full screen width. For a React Native app, that means breakpoints should not be thought of as a rigid, small set of fixed steps, but the layout must keep looking sensible even at unusual intermediate widths, such as 740 instead of one of the classic Split View values.

In practice this mainly means treating breakpoint boundaries as ranges rather than exact expected values, and checking every layout for consistency independent of the exact pixel count, instead of relying on a small, fixed list of known iPad resolutions that Stage Manager has already made incomplete anyway. A layout that only looks correct at exactly 768 or 1024 pixels wide but breaks at 850 pixels is no longer a robust solution in a Stage Manager world.

8. Testing approach for different multitasking states

The iOS Simulator in Xcode supports Split View and Slide Over directly through the Simulator menu bar, or by manually dragging a second simulated app to the edge of the screen, letting the most important multitasking transitions be tested during development without a physical device. For systematic coverage, a small checklist pays off, covering at minimum the full screen state, the one third and two thirds Split View splits, and Slide Over on both possible sides of the screen.

On top of manual checking, an automated test can be written with Detox or Maestro that renders the app at several simulated window widths and checks through snapshot comparisons whether key layout elements such as navigation bars or action buttons get clipped or overlap at any of the tested widths. These automated checks do not replace real observation on a physical iPad, but reliably prevent a later code change from silently breaking a width that used to work correctly.

9. Practical example: an adaptive grid layout for a product list

A product list view showing three or four columns in full screen mode on a large iPad needs to reduce to two columns in Split View at half screen width and switch to a single column in Slide Over or a very narrow Stage Manager window width, so individual product cards do not get squeezed below a sensible minimum width. The column count should not be derived from a fixed window size table but directly from the available width divided by a defined minimum width per card, so unusual intermediate widths under Stage Manager still produce a clean result.

In practice, a simple formula such as Math.max(1, Math.floor(width / 280)) for a minimum card width of 280 pixels gives a more robust result than a list of fixed breakpoints, because it continuously adapts to any window width instead of visibly jumping or looking wrong at certain intermediate values nobody planned for.


import { useWindowDimensions, FlatList } from 'react-native';

const MIN_CARD_WIDTH = 280;

function ProductGrid({ products }: { products: Product[] }) {
  const { width } = useWindowDimensions();
  const columns = Math.max(1, Math.floor(width / MIN_CARD_WIDTH));

  return (
    <FlatList
      key={columns} // forces a rebuild when the column count changes
      data={products}
      numColumns={columns}
      renderItem={({ item }) => <ProductCard product={item} />}
    />
  );
}
Multitasking mode Typical window width Distinguishing feature Layout consequence
Full screen Full iPad screen width Default starting state Multi column layout possible
Split View (1/2) Roughly half the screen width Two apps visible side by side Reduced column count, more compact spacing
Split View (1/3) Roughly a third of the screen width Narrowest Split View step Single column layout often required
Slide Over Narrow, floating window Vertically shaped regardless of device orientation Fully responsive, single column layout
Stage Manager Freely resizable between minimum and full screen Continuous rather than stepped widths Formula based instead of fixed breakpoints needed

Mironsoft

React Native app development and Magento integration

A mobile app for the Magento shop that actually runs smoothly?

We build React Native apps cleanly connected to the Magento REST or GraphQL API, from the first line of code to publishing on the App Store and Google Play.

App Concept

Plan the architecture and feature scope of a Magento-connected app together.

Magento API Integration

Cleanly connect product catalog, cart, and checkout to the shop API.

Store Publishing

Guide the App Store and Google Play release process without pitfalls.

10. Summary

iPad Split View and Multitasking: Key Takeaways

Detection

useWindowDimensions returns the current window width and automatically triggers a re-render on every change.

Strategy

Flexbox instead of fixed pixel values, paired with clearly defined breakpoints for structural layout decisions.

Configuration

UIRequiresFullScreen, or ios.requireFullScreen, must be set to false for multitasking to work at all.

Stage Manager

Freely resizable windows require formula based rather than rigidly stepped layout decisions.

11. FAQ: iPad Split View and Multitasking: Key Takeaways

1Which multitasking modes does an iPad app generally need to support?
Full screen, Split View at different width ratios, Slide Over as a floating narrow window, and on newer iPads additionally Stage Manager with freely resizable, overlapping windows.
2How does a React Native app detect a window size change at runtime?
Through the useWindowDimensions hook, which returns the current width and height and automatically triggers a re-render of the component whenever those values change due to a multitasking switch.
3Why is Dimensions.get('window') problematic for multitasking?
Because this function only returns the value once at the time it is called and does not react to later changes. useWindowDimensions should be used instead for continuously correct behavior.
4Why is a check like Platform.isPad unreliable for responsive layouts?
Because it checks the device class rather than the actually available window width and still returns true even while the app runs in a narrow Slide Over window. Layout decisions should instead be based on the actual width.
5What is a useBreakpoint hook and what is it used for?
A central hook that translates the current window width into named categories such as compact, regular and expanded, similar to the size class concept from UIKit, so every component in the app uses the same width thresholds.
6Which Info.plist setting is critical for Split View and Slide Over?
The UIRequiresFullScreen key must either be absent or explicitly set to false, or ios.requireFullScreen in app.json for Expo projects. Otherwise the app is permanently excluded from the multitasking pool.
7How does Stage Manager change the requirements for a responsive layout?
Stage Manager allows freely resizable window sizes instead of a limited set of fixed Split View ratios, which is why layouts should react formula based rather than to a rigid, fixed set of expected width values.
8How does multitasking affect an app's safe area insets?
The effective safe area insets can differ between Split View or Slide Over mode and full screen mode, because the app's area shifts relative position within the physical screen. SafeAreaProvider updates these values automatically.
9How can Split View and Slide Over be tested without a physical iPad?
The iOS Simulator in Xcode supports both modes directly through the Simulator menu bar as well as by manually dragging a second simulated app to the edge of the screen, making the key transitions testable during development.
10How can a robust column count be calculated for a grid layout?
Through a formula such as Math.max(1, Math.floor(width / minimum card width)) instead of a fixed list of breakpoints, since this formula continuously adapts to any window width and still works cleanly at unusual Stage Manager intermediate widths.