RORK LABJP
ENGINE — Rork Max is powered by Claude Code and Claude Opus 4.6, generating native Swift apps directlyCORE ML — Rork Max reaches on-device Core ML inference alongside HealthKit, HomeKit, NFC, and App ClipsSEED — Rork raised a $15M seed led by Left Lane Capital in April 2026, joined by Peak XV and a16z SpeedrunM&A — Rork acquired the app builder Paperline and says it will stay acquisitive to bring in engineering talentMARKET — Gartner expects 75% of new applications to be built with low-code or no-code tools by the end of 2026GROWTH — The no-code AI platform market is projected to grow from $4.9B in 2024 to $24.8B by 2029ENGINE — Rork Max is powered by Claude Code and Claude Opus 4.6, generating native Swift apps directlyCORE ML — Rork Max reaches on-device Core ML inference alongside HealthKit, HomeKit, NFC, and App ClipsSEED — Rork raised a $15M seed led by Left Lane Capital in April 2026, joined by Peak XV and a16z SpeedrunM&A — Rork acquired the app builder Paperline and says it will stay acquisitive to bring in engineering talentMARKET — Gartner expects 75% of new applications to be built with low-code or no-code tools by the end of 2026GROWTH — The no-code AI platform market is projected to grow from $4.9B in 2024 to $24.8B by 2029
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.

Rork498Android 15edge-to-edgeReact Native201Expo139SafeArea3Troubleshooting37

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-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.
Dev Tools2026-07-08
Your SVG Icon Shows in Expo Go but Vanishes in a Build — Making SVGs Render Reliably in Rork Apps
When a .svg import renders nothing, throws a resolve error, or ignores your theme colors in Rork and Expo apps, here is how to fix it with metro.config.js, react-native-svg-transformer, and currentColor — with working code.
📚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 →