【Expo/React Native】Androidのナビゲーションバーを非表示にする方法|SDK54以降の最新対応版

Androidアプリ

対象読者:

  • Expo(React Native)でAndroidアプリを開発しており、画面下部の「ナビゲーションバー(システムバー)」を非表示にしたい方。
  • NavigationBar.setVisibilityAsync is deprecatedCannot find native module 'ExpoNavigationBar' のエラーで詰まっている方。

この記事でわかること

  • Expo SDK 54以降でAndroidの「edge-to-edge」表示が強制になった背景
  • expo-navigation-bar の非推奨API(setVisibilityAsync / setBehaviorAsync)と新しい書き方
  • Cannot find native module 'ExpoNavigationBar' エラーの原因と解決策
  • 実際に手を動かして解決するまでの手順

なぜ今までのやり方が使えなくなったのか?

Expo SDK 54(React Native 0.81)から、Android 16をターゲットにしたことで edge-to-edge(画面端から端までの表示)がすべてのAndroidアプリで強制されるようになりました。これはOSレベルの仕様変更であり、アプリ側で無効化することはできません。

この変更に伴い、expo-navigation-bar パッケージの多くのAPIが 「no-op(呼び出しても何も起きない)」化 されました。具体的には以下のメソッドです。

  • setBackgroundColorAsync
  • setBorderColorAsync
  • setBehaviorAsync
  • setPositionAsync
  • setButtonStyleAsync

これらは「ナビゲーションバーの背景色」や「スワイプ時の挙動」を細かく制御するためのAPIでしたが、edge-to-edgeが標準になったことで意味を持たなくなり、非推奨(Deprecated)となっています。

新しいAPI:NavigationBar コンポーネントと setHidden

現在の expo-navigation-bar では、表示・非表示の制御は以下のどちらかの方法で行います。

方法1:コンポーネントで宣言的に指定する(推奨)

TypeScript

import { NavigationBar } from "expo-navigation-bar";

export default function App() {
  return (
    <>
      <NavigationBar hidden={true} />
      {/* アプリ本体 */}
    </>
  );
}

方法2:命令的に呼び出す

TypeScript

import { useEffect } from "react";
import { NavigationBar } from "expo-navigation-bar";

export default function App() {
  useEffect(() => {
    NavigationBar.setHidden(true);
  }, []);
  
  return (
    // アプリ本体
  );
}

[!CAUTION] setVisibilityAsync("hidden") のような旧APIは今後のバージョンで削除される予定です。新規実装では上記の書き方に統一しておくのが安全です。

ビルド時に固定したい場合(config plugin)

実行時ではなく、ビルドの段階で挙動を固定したい場合は app.json に config plugin を追加します。

JSON

{
  "expo": {
    "plugins": [
      ["expo-navigation-bar", { "hidden": true }]
    ]
  }
}

※この設定を反映するには、後述する prebuild によるネイティブコードの再生成が必要です。

「Cannot find native module ‘ExpoNavigationBar’」の原因と対処法

expo-navigation-bar を導入してコードを書き換えたのに、実機やエミュレータで以下のエラーが出るケースがあります。

Plaintext

Error: Cannot find native module 'ExpoNavigationBar'

これは非常によくあるハマりポイントで、原因は大きく2つあります。

原因1:Expo Goで実行している

expo-navigation-bar はネイティブコードを含むモジュールのため、ストア版の Expo Goアプリでは動作しません。Development Build(expo-dev-client)でのみ利用可能です。

原因2:過去にビルドしたアプリ(バイナリ)をそのまま使っている

これが一番の盲点です。npm run startexpo start)は JavaScriptのバンドラを起動するだけ のコマンドであり、実機にインストール済みのネイティブアプリ自体を更新しません。

つまり、expo-navigation-bar を後から npm install しても、過去にビルドしたアプリのバイナリにはそのネイティブモジュールが組み込まれていません。そのため、JS側から呼び出そうとしても「ネイティブ側に実体がない」となりエラーになります。

解決策:ネイティブアプリを作り直す

ネイティブモジュールを追加・変更したときは、必ずアプリ本体を再ビルド・再インストールする必要があります。

ローカルで再ビルドする場合

Bash

npx expo prebuild --platform android --clean
npx expo run:android

EAS Buildを使っている場合

Bash

eas build --profile development --platform android

ビルドが完了したら、生成されたアプリを実機に入れ直してから、あらためて npm run start を実行してください。

[!TIP] 「JSコードの変更だけなら再ビルド不要、ネイティブモジュールが絡む変更は必ず再ビルドが必要」という原則を覚えておくと、今後の開発でもハマらなくなります。

まとめ:作業手順のチェックリスト

  1. npx expo install expo-navigation-bar でパッケージを追加する
  2. <NavigationBar hidden={true} /> または config plugin で非表示設定を行う
  3. npx expo prebuild --clean でネイティブプロジェクトを再生成する
  4. npx expo run:android(または EAS Build)でアプリを再ビルドし、実機に入れ直す
  5. npm run start でMetroを起動し、動作確認する

この手順さえ踏めば、SDK 54以降のedge-to-edge環境でも問題なくナビゲーションバーを非表示にできます。

よくある質問(FAQ)

Q. iOSでも同じようにホームインジケーターを非表示にできますか?

A. できません。iOSでは通常のアプリに対してホームインジケーターの非表示は基本的に許可されておらず、ゲームなどの一部の例外を除いて、Expo公式からも同様の簡易APIは公開されていません。

Q. ナビゲーションバーを非表示にすると、ユーザーは操作できなくなりませんか?

A. 非表示にしても、画面端からスワイプすれば一時的にナビゲーションバーを呼び出せます。これはAndroid OS標準の挙動(Immersive Mode)で、アプリ側から変更することはできません。

Q. expo-navigation-bar はExpo Goで試せますか?

A. 試せません。ネイティブコードを含むため、Development Buildまたは本番ビルドでのみ動作します。

コメント

タイトルとURLをコピーしました