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-02中級

Rork で StatusBar の色・スタイルが反映されない時の対処法

Rork で生成したアプリの StatusBar が iOS と Android で意図通りに表示されない問題を、実装パターン別に切り分けて解決する手順をまとめました。

Rork515StatusBarexpo-status-barReact Native209iOS108Android43トラブルシューティング77

App Store の審査に出した後、知人から「上のバッテリーアイコンが見えないよ」と連絡が来たことがあります。明るい背景に白いアイコンが乗ってしまっていたのです。Rork が生成したコードでは StatusBar まわりは見落とされやすく、特に画面遷移を挟むと突然色が変わる、Android だけ背景色が反映されない、といった現象が頻繁に起こります。

ここでは私が実際にリリースしたアプリで踏んだトラブルを基に、StatusBar の色やスタイルが思った通りに表示されない問題を切り分け、確実に直す手順を整理しました。expo-status-bar と React Native 標準の StatusBar の使い分けを含め、本番で困らない構成までまとめています。

まず確認すべきこと — どのライブラリを使っているか

Rork で生成された画面コードには、たいてい次の 2 種類のいずれかが含まれています。

  • import { StatusBar } from 'expo-status-bar' — Expo 推奨。SDK 50 以降ではこちらが標準
  • import { StatusBar } from 'react-native' — React Native 標準。プラットフォーム差が大きい

私は基本的に expo-status-bar を使い、Android で背景色を変えたい時だけ react-native の StatusBar を併用する方針で固めています。expo-status-bar は iOS/Android の差異を吸収してくれる薄いラッパーなので、まずはこちらを使い切ることをおすすめします。

両方のインポートが混在していると、内部で別々のインスタンスを参照することになり、設定が打ち消し合って原因不明の挙動になります。プロジェクト全体で一本化しましょう。

ケース 1: アイコンが背景に溶けて見えない

最も多いのがこのパターンです。明るい背景に白い文字、暗い背景に黒い文字が乗ってしまい、時刻やバッテリーが視認できません。

// app/(tabs)/index.tsx
import { StatusBar } from 'expo-status-bar';
import { View, Text } from 'react-native';
 
export default function HomeScreen() {
  return (
    <View style={{ flex: 1, backgroundColor: '#FFFFFF' }}>
      {/* 明るい背景なので、アイコンは黒(dark)で表示 */}
      <StatusBar style="dark" />
      <Text>こんにちは</Text>
    </View>
  );
}

style プロパティは次の 3 つを取ります。

  • light — アイコンを白く描画(暗い背景用)
  • dark — アイコンを黒く描画(明るい背景用)
  • auto — システムの配色に追従(多くの場合これで十分)

ホーム画面が dark、設定画面が light のように画面ごとに値が変わる場合は、各 Screen コンポーネント内で StatusBar を宣言してください。_layout.tsx で一度だけ宣言しても、expo-status-bar は最後にマウントされたものを優先するため、画面遷移で揺らぎます。

ケース 2: Android だけ背景色が反映されない

iOS の StatusBar には背景色の概念が無く、画面の View がそのまま透けて見えています。一方 Android はステータスバーが独立した領域を持ち、明示的に色を指定しないとデフォルトの黒のままです。

import { StatusBar } from 'expo-status-bar';
import { Platform, StatusBar as RNStatusBar, View } from 'react-native';
 
export default function ScreenWithColoredBar() {
  return (
    <View style={{ flex: 1 }}>
      {/* iOS は expo-status-bar に任せる */}
      <StatusBar style="light" />
      {/* Android のみ背景色を指定 */}
      {Platform.OS === 'android' && (
        <RNStatusBar backgroundColor="#1E3A8A" barStyle="light-content" />
      )}
      {/* 画面コンテンツ */}
    </View>
  );
}

「Android で背景色を変えたいから RN 標準を使う」「iOS のスタイル切り替えは expo に任せる」というハイブリッド構成にしておくと、双方の良いところを取れます。Android 15 のエッジ・トゥ・エッジ表示では backgroundColor の挙動が変わる可能性があるため、react-native-edge-to-edge の導入も検討してください。

ケース 3: 画面遷移で色が点滅する

タブ切り替えやスタックナビゲーションの遷移中に、一瞬だけ前画面のスタイルが残る現象です。これは StatusBar の更新タイミングが遷移アニメーションより遅いことが原因で起こります。

Expo Router を使っている場合は、useFocusEffect と組み合わせて、画面がフォーカスされた瞬間に StatusBar を更新します。

import { useFocusEffect } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import { useCallback, useState } from 'react';
import { View } from 'react-native';
 
export default function SettingsScreen() {
  const [style, setStyle] = useState<'light' | 'dark'>('dark');
 
  // 画面がフォーカスされる度に StatusBar を再宣言
  useFocusEffect(
    useCallback(() => {
      setStyle('light');
      return () => {
        // 離脱時は何もしない(次画面が再宣言するため)
      };
    }, []),
  );
 
  return (
    <View style={{ flex: 1, backgroundColor: '#0F172A' }}>
      <StatusBar style={style} animated />
      {/* ... */}
    </View>
  );
}

animated プロパティを付けると、色の切り替えにフェードが入って点滅が緩和されます。逆にチラつきが許容できないアプリ(金融系など)では animated={false} にして、急激に切り替える方が「動作している感」が伝わります。私はコンテンツ系のアプリでは animated を付け、業務系では外しています。

ケース 4: モーダル表示中に色が戻ってしまう

Modal コンポーネントを表示すると、StatusBar のスタイルが OS 標準に戻されてしまうことがあります。これは Modal が独自のウィンドウとしてマウントされ、親ビューの StatusBar 設定が伝播しないためです。

import { Modal, View } from 'react-native';
import { StatusBar } from 'expo-status-bar';
import { useState } from 'react';
 
export default function ScreenWithModal() {
  const [open, setOpen] = useState(false);
 
  return (
    <View style={{ flex: 1 }}>
      <StatusBar style="dark" />
 
      <Modal visible={open} onRequestClose={() => setOpen(false)}>
        <View style={{ flex: 1, backgroundColor: '#000' }}>
          {/* Modal 内でも StatusBar を再宣言 */}
          <StatusBar style="light" />
          {/* モーダルのコンテンツ */}
        </View>
      </Modal>
    </View>
  );
}

ポイントは Modal の中身でも StatusBar を再宣言することです。閉じた後は親側の宣言が再度効くので、明示的に戻す処理は不要です。

iOS の presentationStyle="fullScreen" ではこれで十分ですが、pageSheetformSheet だと OS 側がスタイルを管理してしまうため、StatusBar の再宣言が無視されます。デザイン優先で表示形式を選ぶのがおすすめです。

ケース 5: SafeAreaView を使っていて余白が崩れる

StatusBar の問題は、SafeAreaView のインセット計算とも絡みます。translucent を有効にしている場合、コンテンツが StatusBar の裏まで広がるため、ヘッダーが切れて見えることがあります。

expo-status-bartranslucent プロパティを使うと、Android のステータスバーが透明になり、その分インセットを react-native-safe-area-contextuseSafeAreaInsets から取得して padding を確保する必要が出てきます。

import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { StatusBar } from 'expo-status-bar';
import { Platform, View } from 'react-native';
 
export default function TranslucentBar() {
  const insets = useSafeAreaInsets();
 
  return (
    <View style={{ flex: 1 }}>
      <StatusBar style="light" translucent />
      <View
        style={{
          paddingTop: Platform.OS === 'android' ? insets.top : 0,
          backgroundColor: '#1E3A8A',
        }}
      >
        {/* ヘッダー */}
      </View>
    </View>
  );
}

translucent を使うかどうかは、デザインがエッジ・トゥ・エッジを採用しているかで決まります。最近の Material You デザインでは透過が前提なので、新規アプリならこちらを推奨します。Safe Area の扱いについては Rork で Safe Area・ノッチ表示が崩れる問題の解決ガイド に詳しく書きました。

デバッグの順番

ここまで読んで「自分のはどれだろう」と迷った方のために、私が普段やっている切り分け手順を共有します。

  1. iOS シミュレータと Android エミュレータの両方で同じ画面を開く
  2. 両方とも問題があれば、StatusBar の宣言自体が無いか、auto のまま放置されている可能性が高い
  3. Android だけ問題があれば、backgroundColor の指定漏れか translucent の影響を疑う
  4. iOS だけ問題があれば、presentationStyle の指定が悪さをしている可能性がある
  5. 画面遷移で起こるなら、画面ごとに StatusBar が宣言されているかを確認する
  6. プラットフォーム差全般のチェックリストは Rork で iOS と Android の挙動が違う時のチェックリスト も参照ください

iOS シミュレータでは Cmd + Shift + H でホームに戻すと StatusBar の状態がリセットされるので、再現性の確認に使えます。Android エミュレータは「Settings」アプリ内で外観を切り替えると、システムテーマと自分のアプリの相互作用が見やすくなります。

時間を節約してくれる小さな習慣

最後に、私が実際に取り入れて効果のあった「StatusBar 不具合を未然に防ぐ習慣」を 3 つ紹介します。どれもリリース前に取り入れられる軽い工夫です。

ひとつ目は、画面テンプレートに StatusBar を組み込んでおくこと。新しい画面を作る時、最初から <StatusBar style="auto" /> がリターンの先頭に書いてあるスニペットからコピーしています。デザインが固定スタイルを要求した時には autodarklight に書き換えるだけ。最初から宣言があれば、StatusBar が抜け落ちたままリリースされる事故は起きません。

ふたつ目は、早い段階で実機で確認すること。シミュレータとエミュレータは大抵正しく描画してくれますが、動画再生・スクリーンショット撮影・回転といった動作を実機で行うと、シミュレータでは出ない不具合が見つかることがあります。私は今、App Store 提出の前に必ず実機の iPhone と廉価な Android 端末で全画面の StatusBar をチェックするようにしています。20 分で終わる作業ですが、レビューで「アイコンが見えません」と書かれるダメージに比べれば誤差です。

みっつ目は、監査を自動化すること。私は Detox か Maestro で全画面を巡回してスクリーンショットを撮るだけの簡易フローを用意しています。サムネイル 40 枚程度を眺めるのは 1 分で済み、コントラスト問題は一目で見つかります。自動化が間に合わないなら、iOS のコントロールセンターを下ろした状態で各画面を手動で確認するだけでも十分多くの問題を拾えます。

複数の Rork プロジェクトで同じバグと戦っているなら、共通コンポーネントに抽出するサインです。私は ThemedStatusBar という薄いラッパーを個人テンプレートリポジトリに持っており、theme プロパティ 1 つを受け取って iOS/Android の分岐を内部で処理しています。20 行ほどのコードですが、何度も元を取ってくれている小さな相棒です。

全体を振り返って

StatusBar は地味ですが、ここがおかしいだけで「作りが雑な印象」が一気に出てしまうので、リリース前に必ず両プラットフォームで確認してください。具体的なアクションとしては、まず使っているライブラリを expo-status-bar に統一し、各画面コンポーネントに 1 行 <StatusBar style="..." /> を入れることから始めるのが効果的です。それだけでケース 1 と 2 の半数は解決します。

スプラッシュ画面から本編に切り替わる瞬間の挙動が気になる場合は、Rork のスプラッシュ画面が固まる・白フラッシュする問題の解決法 もあわせて確認すると、起動時のちらつきまで一気に潰せます。

シェア

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

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

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

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

関連記事

開発ツール2026-04-24
Rork アプリの WebView が真っ白になる・ページが表示されないときに確認する 6 つの原因
Rork で WebView を組み込んだら画面が真っ白になる、ページが読み込まれない、JavaScript が動かない ─ そんな症状を切り分けて確実に直すためのチェックリストです。
開発ツール2026-04-18
RorkアプリがiOSで動くのにAndroidだけおかしい:プラットフォーム差異を修正する実践ガイド
RorkアプリがiOSで動くのにAndroidで崩れる問題を解決します。シャドウ・フォント・権限・キーボード制御など主要なプラットフォーム差異を実例コードで解説します。
開発ツール2026-05-19
Rork で AsyncStorage に大容量データを保存すると Android で CursorWindow エラーが出る原因と対処
Rork(React Native)で AsyncStorage に大きな JSON や画像メタデータを保存すると Android で発生する Row too big to fit into CursorWindow エラーの原因と、MMKV・SQLite・分割保存・圧縮など複数の現実的な対処をまとめています。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →