SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ExpoとEASで始める快適モバイルアプリ開発

Expo Routerのレイアウトの仕組みを理解し、より実践的なナビゲーションを構築しよう

ExpoとEASで始める快適モバイルアプリ開発 第6回

  • X ポスト
  • このエントリーをはてなブックマークに追加

スタックナビゲーション

 モバイルアプリで最も一般的なナビゲーションパターンのひとつが「スタックナビゲーション」です。これは、新しい画面が前の画面の上に積み重なるように表示され、ユーザーは「戻る」操作で前の画面に戻ることができる、というものです。

 例えば、商品一覧画面から商品詳細画面へ遷移し、さらにレビュー投稿画面へ進む、といった一連の流れを想像すると分かりやすいでしょう。多くのOSで標準的な「戻る」ボタン(ヘッダーの左矢印や、Androidの物理/ジェスチャーバックボタン)がこのスタックの操作と連動します(図4)。

図4:スタックナビゲーションのイメージ
図4:スタックナビゲーションのイメージ

 Expo Routerでは、このスタックナビゲーションを簡単に実装するための仕組みが提供されています。expo-routerパッケージに含まれるStackコンポーネントをレイアウトルート (_layout.js) で使用します。

基本的なスタックナビゲーションの設定

 特定の画面群(例えば設定関連の画面すべて)にスタックナビゲーションを適用したい場合、それらの画面ファイルを一つのディレクトリにまとめ、そのディレクトリ直下にレイアウトルートファイル (_layout.js) を作成します。そして、この_layout.jsからStackコンポーネントをエクスポートします。

 例として、app/settings/ディレクトリ内に設定関連の画面 (index.js, profile.js, notifications.js) を配置し、これらをスタックナビゲーションで管理するケースを考えます。ファイル構成はリスト3のようになります。

[リスト3]ファイル構成例
app/
├── settings/
│   ├── _layout.js         // settingsディレクトリ用スタックナビゲーションのレイアウト
│   ├── index.js           // /settings (設定トップ画面)
│   ├── profile.js         // /settings/profile (プロフィール編集画面)
│   └── notifications.js   // /settings/notifications (通知設定画面)
└── _layout.js             // アプリ全体のルートレイアウト

 図4のようなイメージの画面遷移ができるとよいですね。

図5:ファイル構成とスタックナビゲーションの関係
図5:ファイル構成とスタックナビゲーションの関係

 これを実現するには、app/settings/_layout.jsの内容はリスト4のようになります。

[リスト4]app/settings/_layout.js
// app/settings/_layout.js
import { Stack } from 'expo-router';

export default function SettingsStackLayout() {
  return (
    <Stack>
      {/* (1) 各画面のヘッダー設定などをここで行う */}
      <Stack.Screen name="index" options={{ title: '設定' }} />
      <Stack.Screen name="profile" options={{ title: 'プロフィール編集' }} />
      <Stack.Screen name="notifications" options={{ title: '通知設定' }} />
    </Stack>
  );
}

 このapp/settings/_layout.jsが、settingsディレクトリ内のすべての画面ファイル (index.js, profile.js, notifications.js) に対する共通レイアウトとして機能します。Stackコンポーネントを返すことで、これらの画面がスタックとして管理されるようになります。

 (1)のようにStackコンポーネントの子要素として<Stack.Screen name="ファイル名" options={{...}} />を記述することで、各画面がスタックに登録され、ヘッダーのタイトル ( options={{ title: '...' }}) などのナビゲーションオプションを指定できます。

 name属性には、settingsディレクトリ内のファイル名(拡張子なし)を指定します。例えばindex.jsならindexprofile.jsならprofileです。

 これにより、/settings(settings/index.js) から/settings/profile (settings/profile.js) へLinkコンポーネントで遷移すると、profile.jsの画面がindex.jsの画面の上に重なって表示され、ヘッダーには自動的に「戻る」ボタンと「プロフィール編集」というタイトルが表示されます(図6)。

図6:settingsの画面遷移
図6:settingsの画面遷移

 スタックナビゲーションを利用することで、進んだり戻ったりする基本的な画面遷移を簡便に実装できますね。

タブナビゲーション

 スタックナビゲーションと並んで、モバイルアプリで頻繁に用いられるのが「タブナビゲーション」です。

 これは通常、画面の下部(時には上部)に複数のタブが配置され、各タブをタップすることで対応する画面に切り替わるというインターフェースです。アプリの主要な機能セクションへのショートカットとして機能し、ユーザーは少ない操作で目的の画面に素早くアクセスできます(図7)。

図7:タブナビゲーションの例
図7:タブナビゲーションの例

 Expo Routerでは、このタブナビゲーションもexpo-routerパッケージに含まれるTabsコンポーネントをレイアウトルート (_layout.js) で使用することで簡単に実装できます。

基本的なタブナビゲーションの設定

 タブナビゲーションをアプリの主要な画面群(例:ホーム、検索、マイページなど)に適用するには、これらの画面をグループルートでまとめ、そのグループのレイアウトルート (app/(tabs)/_layout.jsなど) で Tabsコンポーネントをデフォルトエクスポートします。

 例えば、ホーム画面 (home.js)、検索画面 (search.js)、マイページ画面 (mypage.js) をタブで切り替えられるようにしたい場合、リスト5のようなファイル構成になります。

[リスト5]ファイル構成例
app/
├── (tabs)/
│   ├── _layout.js  // タブナビゲーションのレイアウト定義
│   ├── home.js     // /home (ホーム画面)
│   ├── search.js   // /search (検索画面)
│   └── mypage.js   // /mypage (マイページ画面)
└── _layout.js      // アプリ全体のルートレイアウト

 これらのファイルをタブナビゲーションで扱うには、リスト6のように登録します。

[リスト6]app/(tabs)/_layout.js
// app/(tabs)/_layout.js
import { Tabs } from 'expo-router';
import { FontAwesome } from '@expo/vector-icons'; // アイコン表示のため

export default function TabLayout() {
  return (
    <Tabs
      screenOptions={{ // (6)
        // tabBarActiveTintColor: 'blue', // アクティブなタブの色などを指定できる
      }}
    >
      <Tabs.Screen
        name="home" // (1)
        options={{ // (2)
          title: 'ホーム', // (3)
          tabBarIcon: ({ color, size }) => ( // (4)
            <FontAwesome name="home" size={size} color={color} />
          ),
        }}
      />
      <Tabs.Screen
        name="search"
        options={{
          title: '検索',
          tabBarIcon: ({ color, size }) => (
            <FontAwesome name="search" size={size} color={color} />
          ),
        }}
      />
      <Tabs.Screen
        name="mypage"
        options={{
          title: 'マイページ',
          tabBarIcon: ({ color, size }) => (
            <FontAwesome name="user" size={size} color={color} />
          ),
          // (5)
          headerShown: false, // ヘッダーを非表示にする場合
        }}
      />
    </Tabs>
  );
}

 この(tabs)/_layout.jsが、(tabs)ディレクトリ内のすべての画面 (home.js, search.js, mypage.js) に対するレイアウトとして機能し、Tabsコンポーネントを返すことで、これらの画面がタブインターフェースで管理されるようになります。Tabsコンポーネントの直下には<Tabs.Screen ... />を配置し、各タブに対応する画面を指定します。

 (1)のname属性には、グループルート内のファイル名(拡張子なし)を指定します。(2)の options属性では、各タブの見た目や挙動をカスタマイズします。(3)のtitleプロパティはタブのラベルや、そのタブが選択されている時のヘッダータイトルとして使用されます。(4)のtabBarIconは、タブに表示されるアイコンを指定する関数です。引数としてcolorsizeを受け取り、アイコンコンポーネントを返します。上記の例では@expo/vector-iconsFontAwesomeを使用しています。(5)のheaderShown: falseを指定すると、そのタブがアクティブな時にデフォルトで表示されるヘッダーを非表示にできます(図8)。

図8:ヘッダーを消すこともできる
図8:ヘッダーを消すこともできる

 Tabsコンポーネント自体の設定である(6)のscreenOptionsプロパティでは、すべてのタブに共通のオプション(例:アクティブなタブのアイコンやラベルの色tabBarActiveTintColor)を指定することも可能です。

次のページ
動的ルート

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
ExpoとEASで始める快適モバイルアプリ開発連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 中川幸哉(ナカガワユキヤ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/21710 2025/06/20 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング