🥶

# React NativeでAndroidのナビゲーションバーを透過にする方法

2025/03/02に公開

概要

本記事では、React Native(Expo)アプリでAndroidのナビゲーションバーを透明(透過)にする方法を解説します。Androidデバイスの画面下部に表示されるナビゲーションバーを透過に設定し、アプリのコンテンツを画面端まで表示する実装手順を詳しく説明します。
具体的には、Expoのライブラリであるexpo-navigation-barを使用し、コード上でナビゲーションバーの背景色を透明に設定する方法や、Expo Router 利用時のコード例、さらにSafeAreaViewKeyboardAvoidingViewとの併用時の注意点、Expo Go上での挙動についても取り上げます。

導入: ナビゲーションバーを透過にする理由

Androidアプリでは通常、下部にシステムのナビゲーションバー(戻るボタンやホームボタンのエリア)が表示され、デフォルトでは黒やグレーの背景色が付いています。これを透過(透明)にすることで、アプリの内容を端から端まで(edge-to-edge)表示でき、より没入感のあるデザインを実現できます。

https://developer.android.com/design/ui/mobile/guides/foundations/system-bars#:~:text=,edge

実際、背景画像を全面に敷いたデザインやフルスクリーンのコンテンツでは、ナビゲーションバーが黒く塗りつぶされていると全体の美観を損ねてしまいます。ナビゲーションバーを透明にすれば、その背後にアプリの背景やコンテンツを表示できるため、UIの一体感が増しユーザー体験の向上につながります。

例えば、写真や動画を全画面で表示するビューや、背景にグラデーションやイラストを配置している場合、ナビゲーションバーまで含めて表示できればコンテンツをより引き立てることができます。また、Androidの最新ガイドラインでもシステムバー(ステータスバーやナビゲーションバー)を透明または半透明にしてコンテンツをその背後まで描画することが推奨されています。

https://developer.android.com/design/ui/mobile/guides/foundations/system-bars#:~:text=,edge

こうした理由から、Androidアプリでナビゲーションバーを透過に設定したいケースがあるわけです。

実装手順

それでは、React Native(Expo)アプリでAndroidのナビゲーションバーを透過にする実装手順を説明します。Expoを利用している前提で進めますが、Bare React Nativeの場合でも原理は同じです(nativeコードの設定が必要になります)。Expoでは公式にexpo-navigation-barというモジュールが提供されており、これを使うことで簡単にナビゲーションバーの表示をカスタマイズできます。

1. expo-navigation-barのインストール

まずはExpoプロジェクトにexpo-navigation-barを追加します。以下のコマンドを実行してライブラリをインストールしてください。

npx expo install expo-navigation-bar

ExpoのManaged Workflowであれば、上記コマンドで必要なモジュールがインストールされます(ネイティブコードのリンクは自動的に行われます)。

2. ナビゲーションバーを透過に設定するコード

次に、アプリ起動時にナビゲーションバーを透過させるコードを追加します。expo-navigation-barから提供される NavigationBar API を使用します。具体的には、ナビゲーションバーの位置を絶対配置に変更し(画面上にオーバーレイ表示)、背景色を透明に設定します。これにより、アプリのコンテンツがナビゲーションバーの背後まで描画されるようになります。

App.js(抜粋)
import * as NavigationBar from 'expo-navigation-bar';
import { useEffect } from 'react';

export default function App() {
  useEffect(() => {
    // ナビゲーションバーを画面上に重ねる(absolute)設定に
    NavigationBar.setPositionAsync('absolute');
    // ナビゲーションバーの背景色を透明に設定
    NavigationBar.setBackgroundColorAsync('transparent');
    // (オプション)ナビゲーションバーのボタンアイコンのスタイルを設定
    NavigationBar.setButtonStyleAsync('light');
  }, []);

  return (
    {/* ...アプリのメインコンポーネント... */}
  );
}

上記のように、useEffectフックを用いてアプリ起動時(コンポーネントマウント時)に一度だけNavigationBarの設定を行います。NavigationBar.setPositionAsync('absolute')ナビゲーションバーを絶対位置(オーバーレイ)に変更し、続けてNavigationBar.setBackgroundColorAsync('transparent')背景を透明に指定しています。
https://github.com/expo/expo/issues/19887#:~:text=jakex7 commented ,101
https://docs.expo.dev/versions/latest/sdk/navigation-bar/#:~:text=%2F%2F enables edge,ffffff00

最後にNavigationBar.setButtonStyleAsync('light')を呼んでいますが、これはナビゲーションバー上のボタン(戻る・ホーム・履歴ボタンなど)の色を設定するものです。背景が暗めのコンテンツの場合は'light'(白系アイコン)、背景が明るいコンテンツの場合は'dark'(黒系アイコン)にすると視認性が向上します。

ここで重要なのは、ナビゲーションバーを透明にする場合、位置をabsoluteにする必要があるという点です。
https://github.com/expo/expo/issues/19887#:~:text=jakex7 commented

位置をデフォルトのrelativeのまま背景だけ透明に指定しても、アプリの描画領域がナビゲーションバーの手前までとなっているため、結果的に下部は空白(デフォルトのグレーや白)のバーが残ってしまいます。absoluteに設定することでアプリの描画領域が画面全体に広がり、背後にコンテンツが描画されて初めて「透明」なバーとして視認できるようになります。

3. Expo Routerを使用している場合の適用方法

Expo Router(ファイルベースルーティング)を使っているプロジェクトでも、基本的な方針は同じです。異なる点は、各スクリーンコンポーネントではなくルートレイアウトで一括してナビゲーションバーの設定を行う点です。Expo Routerでは通常、app/_layout.tsx(またはapp/_layout.js)がアプリ全体のレイアウトコンポーネントになっていますので、そこに先ほどのNavigationBar設定を組み込みます。

app/_layout.tsx(Expo Routerのレイアウト例)
import { Stack } from "expo-router";
import * as NavigationBar from "expo-navigation-bar";
import { useEffect } from "react";

export default function RootLayout() {
  useEffect(() => {
    NavigationBar.setPositionAsync("absolute");
    NavigationBar.setBackgroundColorAsync("transparent");
    NavigationBar.setButtonStyleAsync("dark");
  }, []);

  return <Stack screenOptions={{ headerShown: false }} />;
}

上記は一例ですが、Expo Routerのルートに配置することで、アプリ内のどのスクリーンに遷移してもナビゲーションバーの透過設定が維持されます。<Stack screenOptions={{ headerShown: false }} />はReact NavigationのStackナビゲーションをレンダリングしています(Expo Routerのデフォルト)。必要に応じて他のナビゲーションやレイアウト構造でも同様にuseEffectNavigationBar設定を呼び出してください。

なお、Expo Router環境下で各画面ごとに個別の背景色を持たせている場合(例えばスタックナビゲーションで画面遷移時に別の背景色にしたい等)、透過効果を維持するには各スクリーンの背景を透明にする必要があります。Expo RouterではscreenOptionscontentStyleで各画面の背景色を指定できます。例えば全画面共通で透明背景にするには以下のように設定します。

// 画面コンテンツの背景色を透明に(デフォルトは白)
<Stack screenOptions={{ contentStyle: { backgroundColor: 'transparent' } }}>
   {/* ...screens... */}
</Stack>

こうすることで、各画面コンポーネントのデフォルト背景色を透明に上書きでき、背後の共通の背景(例えばルートレイアウトで設定した背景画像など)がナビゲーションバーの下まで表示されます。

注意点と補足

最後に、ナビゲーションバーを透過化する際の注意点や補足事項について整理します。実装上ハマりやすいポイントや追加で考慮すべき点を確認しておきましょう。

SafeAreaViewとの組み合わせ

Android端末でもノッチや画面丸み、システムバーによるセーフエリアの概念があります。React NativeやExpoではSafeAreaView(もしくはreact-native-safe-area-contextのSafeAreaView)を使ってコンテンツがシステムUIと重ならないよう余白を取ることがあります。しかし、ナビゲーションバーを透過にしてコンテンツをその背後まで表示したい場合、SafeAreaViewがデフォルトで下部に与える余白(ナビゲーションバー分の高さ)は不要になります。もし画面全体を<SafeAreaView style={{flex: 1}}> ... </SafeAreaView>で囲んでいる場合、ナビゲーションバー部分もコンテンツの表示領域から除外されてしまい、結局透明化の恩恵が得られません。

対策として、SafeAreaViewの対象から下端(bottom)を除外します。例えば、react-native-safe-area-contextのSafeAreaViewを使用しているなら、edgesプロパティで適用する辺を指定できます。

<SafeAreaView style={{ flex: 1 }} edges={['top', 'left', 'right']}>
  {/* 画面コンテンツ(下端はSafeAreaを適用しない) */}
</SafeAreaView>

このようにすることで、画面下端にはSafeAreaによる余白を入れず、コンテンツがナビゲーションバーの背後まで描画されます(上端や左右の安全領域は維持されます)。一方で、コンテンツの一部(ボタンやテキストなど)がナビゲーションバーとかぶる可能性もあるため、その場合は個別に下部にパディングを入れるなど調整してください。重要な要素がナビゲーションバー直下に配置されるUIは避け、スクロール可能なリストの場合は下に適切な余白(例えばpaddingBottom: <ナビゲーションバーの高さ>程度)を設けると良いでしょう。

KeyboardAvoidingViewとの併用

ナビゲーションバーを透過にして画面いっぱいにコンテンツを描画している場合、ソフトウェアキーボードの出現に伴うレイアウト変化にも注意が必要です。通常、Androidではキーボード表示時にレイアウトが自動で縮む(windowSoftInputModeadjustResizeであれば)ため、キーボードで隠れないようにしてくれます。しかし、ナビゲーションバーをabsoluteにしているとシステムによる自動調整が意図通りに機能しない場合があります。
https://docs.expo.dev/versions/latest/config/app/#:~:text=your app (similar to ,to manage the keyboard layout
https://docs.expo.dev/versions/latest/config/app/#:~:text=status bar behavior ,to manage the keyboard layout

例えば、テキスト入力欄が画面下部近くにある場合、キーボード表示でそれが隠れてしまうといったケースです。

この対処として、必要に応じてKeyboardAvoidingViewコンポーネント(もしくは手動でScrollViewをスクロールさせる処理)を用いてキーボード出現時にレイアウトを持ち上げる実装を行います。Expoのドキュメントでも、ステータスバーやナビゲーションバーを透明にした場合にはキーボード挙動に不具合が出る可能性があるため、KeyboardAvoidingViewで調整するよう言及されています。
https://docs.expo.dev/versions/latest/config/app/#:~:text=your app (similar to ,to manage the keyboard layout
https://docs.expo.dev/versions/latest/config/app/#:~:text=this property to ,to manage the keyboard layout

具体的には、画面コンポーネントをKeyboardAvoidingViewでラップし、behavior="padding"behavior="height"を設定しておくと、キーボード表示時に子ビューを自動で持ち上げてくれます。透過ナビゲーションバー実装時には、フォーム画面などキーボードを使うUIで念入りにテストを行い、必要ならば適切な対策を講じてください。

Expo Goでの動作について

開発中にExpo Goアプリでプレビューしている場合、ナビゲーションバーの透過設定が反映されないことがあります。これは、Expo Go(Expoのデフォルトクライアントアプリ)ではカスタムのネイティブモジュールや一部のシステムUI操作がサポートされていないためです。expo-navigation-barExpo Goでは完全には機能しない可能性があります(Expo公式ブログでもExpo Goで未サポートである旨が言及されています)。そのため、透過の挙動を確認したい場合は、開発用ビルド(Development Build)や実機への直接ビルド(例えばAndroid APKやApp Bundleの作成)を行い、スタンドアロンアプリとしてテストすることをお勧めします。

まとめ

本記事では、React Native(Expo)アプリでAndroidのナビゲーションバーを透過にする方法について、導入理由から実装手順、注意点まで詳しく解説しました。ナビゲーションバーを透明にすることで、コンテンツを画面いっぱいに表示でき、よりリッチで没入感のあるユーザー体験を提供できます。実装にはExpoのexpo-navigation-barを利用し、

  • NavigationBar.setPositionAsync('absolute')でバーをオーバーレイ表示にする
  • NavigationBar.setBackgroundColorAsync('transparent')でバーの背景色を透明にする

という2つのステップが中心でした。これらをアプリ起動時にuseEffectで実行するだけで、簡単に透過効果が得られます。Expo Router使用時も同様のコードをルートレイアウトで仕込むことで対応可能です。

最後に触れたように、SafeAreaViewの調整によってコンテンツの表示領域を正しく確保し、必要ならKeyboardAvoidingViewでキーボード対応をすることが大切です。また、Expo Goでは動作しない点にも注意しつつ、実際のビルド環境で確認してください。これらのポイントを押さえておけば、Androidアプリのナビゲーションバー透過を効果的に実装できるでしょう。

ぜひ自身のプロジェクトでも試してみて、洗練されたUIを実現してください。🙌

Discussion