RORK LABJP
TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the roundTOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round
Articles/Dev Tools
Dev Tools/2026-05-25Intermediate

Fixing Layout Bleed on Android 15 (API 35) in Rork Apps

Once you bump targetSdkVersion to 35, Android 15 enforces edge-to-edge display, and Rork-generated tab bars and headers start sliding under the system bars. Here are the patterns I use with react-native-edge-to-edge and useSafeAreaInsets to fix it properly.

Rork515Android 15edge-to-edgeReact Native209Expo149SafeArea3Troubleshooting38

Right after I bumped targetSdkVersion from 34 to 35 in Google Play Console, I checked one of my apps on a Pixel 7 and the bottom tab bar had slipped behind the gesture navigation pill. The same screen looked perfectly fine in the preview — only the device running Android 15 was breaking. That pattern has been showing up a lot lately.

The cause is that Android 15 now enforces edge-to-edge display for apps targeting SDK 35 or higher. Rork-generated starter code tends to use React Native's SafeAreaView only at the top of the screen, so when Android 15 changes how the system-bar regions are treated, the layout simply stretches all the way down past the gesture navigation area.

I have been shipping personal apps since 2014, and I have been thrown by layout regressions across major OS bumps more times than I would like to admit. Android 15 has been one of the bigger ones — across the apps that make up my roughly 50 million cumulative downloads, a handful needed an outright layout pass when I raised targetSdkVersion. The patterns below are what I settled on after working through this on real projects, and they slot cleanly into Rork-generated code.

First, confirm what you are looking at

Before assuming it is edge-to-edge enforcement, double-check that you are actually running into it.

# Inspect app.json or app.config.ts
"android": {
  "targetSdkVersion": 35,
  "compileSdkVersion": 35
}

If targetSdkVersion is 34 or lower, edge-to-edge is not enforced. Even on Android 15 devices, the system continues to inset your content as before.

That said, Google Play is requiring targetSdkVersion: 35 for apps submitted from August 2026 onward, so if you plan to update the store listing, this is unavoidable. In a Rork-generated Expo project, the value lives in android/app/build.gradle after expo prebuild.

On the device, this one-liner is the fastest way to confirm you are on the right OS:

adb shell getprop ro.build.version.release
# 15
adb shell getprop ro.build.version.sdk
# 35

Once you have confirmed "Android 15 device + targetSdkVersion 35 build", move on to the fixes.

Fix 1: Adopt react-native-edge-to-edge

From Expo SDK 53 onward, react-native-edge-to-edge is bundled in as the recommended path. If the Rork output is not using it yet, install it first.

npx expo install react-native-edge-to-edge

Then add this to the android section of app.json:

{
  "expo": {
    "android": {
      "edgeToEdgeEnabled": true
    }
  }
}

This alone will not fix the bottom of the screen. Edge-to-edge is built around the idea that the app handles the insets itself, on the assumption that content will overlap with system UI. You still need to wire up your components.

Fix 2: Pull the bottom inset with useSafeAreaInsets

Screens that rely on SafeAreaView alone do not get a reliable bottom inset under Android 15's new model. Reading the value with useSafeAreaInsets and feeding it into paddingBottom is the dependable path.

// app/(tabs)/_layout.tsx
import { Tabs } from "expo-router";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Platform } from "react-native";
 
export default function TabLayout() {
  const insets = useSafeAreaInsets();
 
  return (
    <Tabs
      screenOptions={{
        tabBarStyle: {
          // Reserve room for Android 15's gesture nav strip
          paddingBottom: Platform.OS === "android" ? insets.bottom : 0,
          height: 56 + (Platform.OS === "android" ? insets.bottom : 0),
        },
      }}
    >
      <Tabs.Screen name="index" options={{ title: "Home" }} />
      <Tabs.Screen name="settings" options={{ title: "Settings" }} />
    </Tabs>
  );
}

Devices using gesture navigation report a small insets.bottom (often around 16dp), while three-button navigation lands closer to 48dp. Do not hardcode either — always read from insets.

Fix 3: Add bottom padding to your scrollable areas

Once the tab bar is fixed, the next bite is ScrollView or FlatList whose last item disappears behind the tab bar. Reserve room with contentContainerStyle.

import { ScrollView } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
 
export default function HomeScreen() {
  const insets = useSafeAreaInsets();
  const TAB_BAR_HEIGHT = 56;
 
  return (
    <ScrollView
      contentContainerStyle={{
        paddingBottom: TAB_BAR_HEIGHT + insets.bottom + 16,
      }}
    >
      {/* list content */}
    </ScrollView>
  );
}

I keep TAB_BAR_HEIGHT as a single constant in something like constants/layout.ts. When you eventually adjust the bar height, every screen stays in sync without hunting for magic numbers.

Fix 4: Stop the header from sliding under the status bar

Bleeding can happen at the top too, especially when Rork sets translucent to true via expo-status-bar.

// app/_layout.tsx
import { StatusBar } from "expo-status-bar";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
import { Stack } from "expo-router";
 
export default function RootLayout() {
  return (
    <SafeAreaProvider>
      <SafeAreaView style={{ flex: 1 }} edges={["top"]}>
        <StatusBar style="auto" />
        <Stack />
      </SafeAreaView>
    </SafeAreaProvider>
  );
}

Two things to note: SafeAreaProvider belongs at the very top, and SafeAreaView's edges should be narrowed to ["top"]. If you leave edges unset, iOS pulls the home indicator inset too and the iOS/Android behaviors start to diverge.

Fix 5: Handle bottom sheets and modals

Bottom sheet libraries such as react-native-modal or @gorhom/bottom-sheet also shift under Android 15. Forgetting to add the bottom inset on the sheet itself leaves your primary CTA overlapping the gesture region — a near-guarantee of accidental dismissals.

import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
import { useSafeAreaInsets } from "react-native-safe-area-context";
 
export function CommentSheet() {
  const insets = useSafeAreaInsets();
  return (
    <BottomSheet snapPoints={["50%", "90%"]}>
      <BottomSheetView style={{ paddingBottom: insets.bottom + 24, flex: 1 }}>
        {/* sheet content */}
      </BottomSheetView>
    </BottomSheet>
  );
}

Many sheet libraries handle status bar and keyboard internally, so it is worth checking whether their README mentions "edge-to-edge" or "Android 15" support before assuming you have to do it all yourself.

Verification checklist

When you test on real devices, cover at least three configurations:

  • A Pixel-class phone with gesture navigation (small insets.bottom)
  • A Samsung device pinned to three-button navigation (large insets.bottom)
  • An Android 14 or older device (targetSdkVersion 35 alone does not force edge-to-edge there)

Emulators reproduce most of this, but Samsung's One UI can report slightly different insets, so a single physical device pays for itself fast. I keep an inexpensive Galaxy A model around purely for verification.

Prevention — design every screen with insets in mind

If you build new projects with the assumption that edge-to-edge is the default, none of this becomes a problem again. Asking "who owns the insets on this screen?" as you start each layout is a small habit that pays off enormously when the next OS update lands.

My personal rule is to decide up front whether a screen uses SafeAreaView or useSafeAreaInsets, then leave a comment at the top of the file recording the choice. Even on solo projects, that note pays for itself six months later when you revisit the code.

OS updates will keep coming. With a clear inset strategy in place, they stop turning into emergencies. I hope this saves you the half day I spent figuring it out the first time.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-04-22
Fixing Stuck Splash Screens and White Flash on Launch in Rork Apps
Fixes for the four most common Rork splash screen bugs: a splash that refuses to hide, a white flash on launch, Android 12+ cropping, and dark-mode mismatches.
Dev Tools2026-07-15
The Comma That Fell to the Start of a Line: Rork, Quote Cards, and Japanese Line Breaking
React Native's Text component does not guarantee Japanese line-breaking rules. Here are the violation rates I measured, a WORD JOINER implementation that survives copy and VoiceOver, an onTextLayout audit harness, and how Rork Max (SwiftUI) differs.
Dev Tools2026-07-10
Adding React Compiler to Expo Let Me Delete 41 Hand-Written memo Calls
I enabled React Compiler on Rork-generated React Native screens and measured the rerender counts with Profiler. Here is how I decided which memo and useCallback calls were safe to delete, how to find the components the compiler bailed out on, and how to catch regressions in CI.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →