◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/開発ツール
⬡ 開発ツール/2026-05-02中級

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

Rorkで生成したアプリのStatusBarがiOSとAndroidで意図通りに表示されない問題を、5つのケースで切り分けます。アイコンが背景に溶ける、Androidだけ背景色が効かない、画面遷移で点滅する、モーダルで色が戻るといった症状の対処とデバッグの順番を示します。

Rork585StatusBarexpo-status-barReact Native239iOS115Android55トラブルシューティング85

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" ではこれで十分ですが、pageSheet や formSheet だと OS 側がスタイルを管理してしまうため、StatusBar の再宣言が無視されます。デザイン優先で表示形式を選ぶのがおすすめです。

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

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

expo-status-bar の translucent プロパティを使うと、Android のステータスバーが透明になり、その分インセットを react-native-safe-area-context の useSafeAreaInsets から取得して 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" /> がリターンの先頭に書いてあるスニペットからコピーしています。デザインが固定スタイルを要求した時には auto を dark か light に書き換えるだけ。最初から宣言があれば、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-05-18
Rork で Linking.canOpenURL が iOS だけ false を返す ─ LSApplicationQueriesSchemes 設定漏れの直し方
TikTok や X、LINE 公式アカウントへ飛ばす実装が iOS の本番ビルドだけで動かない症状を、LSApplicationQueriesSchemes の追加と EAS Build の再生成手順で確実に解消します。
⬡ 開発ツール2026-10-07
日本語の見出しだけ太字にならない — Android で fontWeight が効かないときの切り分けと直し方
Rork で作ったアプリで、iPhone では太字なのに Android では日本語の見出しが細いままになる症状の切り分け記事です。原因の見分け方、fontFamily を重みごとに分ける直し方、確認用コードを載せています。
⬡ 開発ツール2026-09-21
exit code 0 で止まるビルド — ログを黙らせていた設定と、空ファイルを通した存在チェック
eas build --local が exit code 0 but produced no further output で止まる件と、0 バイトのスタブが埋め込まれず dyld で落ちる件。どちらも原因は出力を減らす設定でした。自分のスクリプトを棚卸しする手順まで書き残します。