RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-05-25中級

Rork で targetSdkVersion 35 にしたら Android のレイアウトが下まで埋まる問題の直し方

Android 15 (API 35) で強制されるエッジ・トゥ・エッジ表示によって、Rork で生成したアプリの下部タブやヘッダーがシステムバーに食い込む問題を、react-native-edge-to-edge と useSafeAreaInsets を使って実装パターン別に解決します。

Rork515Android 15edge-to-edgeReact Native209Expo149SafeArea3トラブルシューティング77

Google Play Console で targetSdkVersion を 34 から 35 に上げた直後、Pixel 7 の実機で確認したら下部タブバーがジェスチャーナビゲーションのインジケータの裏に潜り込んでいました。プレビューでは何も問題なかった画面が、Android 15 を載せた端末だけで崩れる — このパターンに最近よく出会います。

これは Android 15 から targetSdkVersion 35 以上のアプリに対してエッジ・トゥ・エッジ表示が強制されるようになったことが原因です。Rork で生成された初期コードは React Native の SafeAreaView を画面上部にだけ使っているケースが多く、Android 15 のシステムバー領域の扱いが変わったことに引きずられてレイアウトが下まで伸びてしまいます。

2014年からアプリを個人で出してきた中で、OS のメジャーアップデートに伴うレイアウト崩れには何度も振り回されてきました。今回の Android 15 はその中でもインパクトが大きい部類で、累計5,000万ダウンロードを支えてきた既存アプリ群のいくつかも、targetSdkVersion 引き上げのタイミングで一度作り直しました。ここでは私が実際にハマって整理した対処パターンを、Rork で生成したアプリにそのまま適用できる形でまとめます。

まず確認すべきこと — targetSdkVersion と Android バージョン

問題が起きているのが本当にエッジ・トゥ・エッジ強制が原因なのか、最初に切り分けます。

# app.json または app.config.ts で確認
"android": {
  "targetSdkVersion": 35,
  "compileSdkVersion": 35
}

targetSdkVersion が 34 以下なら、エッジ・トゥ・エッジは強制されません。Android 15 の端末でも従来通り「システムバーを避ける」挙動になります。

一方で、Google Play は 2026年8月以降に提出するアプリに targetSdkVersion: 35 を必須化したため、ストア更新を予定しているなら避けては通れません。Rork が生成する Expo プロジェクトでは、expo prebuild 後の android/app/build.gradletargetSdkVersion が決まります。

実機での再現は次のコマンドで Android のバージョンを確認するのが早道です。

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

これで「Android 15 端末で targetSdkVersion: 35 のビルド」だと確定したら、以下の対処に進みます。

対処 1: react-native-edge-to-edge を導入する

Expo SDK 53 以降では react-native-edge-to-edge が Expo の推奨対応として組み込まれました。Rork が出すコードがこれを使っていない場合は、まずインストールから入ります。

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

app.jsonandroid セクションに次を追記します。

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

これだけでは画面下端のレイアウトは直りません。エッジ・トゥ・エッジは「システム UI と重なる前提でアプリ側がインセットを処理する」という思想なので、コンポーネント側の対応が必要です。

対処 2: useSafeAreaInsets で下部インセットを取る

SafeAreaView だけで囲っている画面では、Android 15 の動作モデルの変更で下部インセットが思った通りに取れません。useSafeAreaInsets で実数値を取り、paddingBottom に渡す方法が確実です。

// 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: {
          // Android 15 のジェスチャーナビゲーション領域を確保
          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>
  );
}

ジェスチャーナビゲーションを使っている端末は insets.bottom0 に近い値(多くは 16dp 程度)になり、3 ボタンナビゲーションでは 48dp 前後になります。固定値ではなく、必ず insets から動的に取ってください。

対処 3: 画面コンテンツのスクロール領域に下端余白を持たせる

タブバーを直したあとに次にぶつかるのが、ScrollViewFlatList の最終アイテムがタブバーの裏に隠れる問題です。contentContainerStylepaddingBottom を確保します。

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,
      }}
    >
      {/* リストの中身 */}
    </ScrollView>
  );
}

ここで TAB_BAR_HEIGHT を定数として外に切り出しておくと、後から高さを変えた時に複数画面の同期が楽になります。私は constants/layout.ts のような場所に集めるようにしています。

対処 4: ステータスバー領域の重なりを直す

下部だけでなく、上部のヘッダーがステータスバーに食い込むケースもあります。Rork が expo-status-bar を使って translucenttrue にしている時に多発します。

// 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>
  );
}

SafeAreaProvider を最上位に、SafeAreaViewedges["top"] に絞るのがポイントです。edges を指定しないと iOS の下部インジケータ領域までインセットを取りに行ってしまい、Android との挙動差が大きくなります。

対処 5: モーダルとボトムシートの底面処理

react-native-modal@gorhom/bottom-sheet を使ったボトムシートも、Android 15 では下端の挙動が変わります。シートの中身に下部インセットを足し忘れると、CTA ボタンがジェスチャー領域と被って誤タップを誘発します。

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 }}>
        {/* シートのコンテンツ */}
      </BottomSheetView>
    </BottomSheet>
  );
}

ボトムシート系は内部でステータスバーやキーボードの処理を持っているライブラリが多いため、ライブラリの README に「edge-to-edge 対応」「Android 15 対応」の項目があるかも合わせて確認してください。

動作確認のチェックリスト

実機で確認する際は、以下の3パターンを最低限カバーしておくと安心です。

  • ジェスチャーナビゲーション有効の Pixel 系(insets.bottom が小さい)
  • 3 ボタンナビゲーション固定の Samsung 端末(insets.bottom が大きい)
  • Android 14 以下の端末(targetSdkVersion 35 でもエッジ・トゥ・エッジは強制されない)

Pixel エミュレータでも再現できますが、Samsung One UI のような OEM カスタマイズではインセットが微妙に違うため、可能なら実機を一台確保しておくと心強いです。私は中古の Galaxy A シリーズを 1 台、検証専用に置いています。

予防策 — レイアウトの最初の一行から考える

Android 15 のエッジ・トゥ・エッジ強制は、新規プロジェクトでは最初から前提として組み込めば困りません。新しい画面を作るたびに「この画面のインセットは誰が処理するか」を意識して書いておくと、後で OS が変わってもまとめて直す手間がほぼゼロになります。

私の場合は、画面ごとに SafeAreaView または useSafeAreaInsets のどちらを使うかを最初に決めて、画面ファイルの先頭にコメントで残すルールにしています。チーム開発でなくても、半年後の自分への申し送りとして効果があります。

OS のアップデートは止められませんが、レイアウトの考え方を整えておけば、変更点ごとに振り回されることは減らせます。同じ問題に取り組んでいる方の参考になれば幸いです。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-04-22
Rork のスプラッシュ画面が消えない・起動直後に白い画面が出る問題の直し方
Rork で作ったアプリのスプラッシュ画面が長時間表示されたまま止まる・起動直後に白い画面が一瞬チラつく・iOSとAndroidで見え方が違う、といった症状の原因と具体的な直し方を、実機で検証したコードとあわせてまとめました。
開発ツール2026-04-20
Rork 生成コードで useEffect が無限ループする原因と直し方
Rorkで生成したReact NativeコードのuseEffectが無限ループする原因を5パターン解説。依存配列の設定ミス・オブジェクト依存・setState競合など具体的なBefore/Afterコードで根本修正する方法をまとめています。
開発ツール2026-04-15
Rorkアプリでキーボードが入力フィールドを隠す問題の完全対処ガイド
Rorkアプリでキーボードが表示されるとテキスト入力フィールドが隠れる問題の原因と解決策を解説します。KeyboardAvoidingView・ScrollView・useKeyboard フックを使った実践的な対処法を紹介します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →