Day 3
Expo UI SwiftUIで3画面タブを作る
@expo/ui/swift-ui の Host と TabView を使い、Today、Tasks、Settings の3画面を切り替えられる最小構成を作ります。各画面では Text を使って、どの画面か分かる状態にします。
動画では、@expo/ui/swift-ui の TabView を使って、Today、Tasks、Settings の3画面を作ります。
この記事では、Host、TabView、Text の役割を確認しながら、3画面を切り替えられるところまで順番に作ります。
今回作るもの
今回は、3つの画面をタブで切り替えられる構成を作ります。
作る画面は以下です。
| 画面 | 役割 |
|---|---|
Today | 表示、レイアウト、進捗、アクションを学ぶ画面 |
Tasks | 入力、一覧、行操作を学ぶ画面 |
Settings | フォーム、セクション、選択系を学ぶ画面 |
この回では、各画面の中身は最小限にします。
src/app/index.tsx の Host の中に TabView を置き、各画面では Text を使って、どの画面を表示しているか分かる状態にします。
今回使うコンポーネント
今回は、@expo/ui/swift-ui から以下のコンポーネントを使います。
| コンポーネント | 役割 |
|---|---|
TabView | 複数の画面をタブで切り替える |
TabView.Tab | TabView の中に表示する1つのタブを定義する |
Host | 第2回で扱ったSwiftUI componentの表示土台 |
Text | 第2回で扱ったテキスト表示 |
第3回の主役は TabView です。
Host は TabView を含む SwiftUI ツリー全体を包むために使います。
Text は各画面の最小表示として使います。
ここで使う TabView は、Expo Router のタブルートではありません。
@expo/ui/swift-ui が提供する SwiftUI component としてのタブ表示です。
作成するファイル構成
第3回では、以下のファイルを作成します。
src/
├── app/
│ └── index.tsx
└── screens/
├── TodayScreen.tsx
├── TasksScreen.tsx
└── SettingsScreen.tsx
components/、data/、types/ は、必要になったタイミングで作成します。
Step 1: 画面ファイルを作る
まず、タブに表示する3つの画面を作ります。
ここでは画面の中身を作り込まず、Text だけを使います。
Host はこのあと src/app/index.tsx で TabView 全体を囲むため、各画面ファイルでは重ねて使いません。
Today画面
src/screens/TodayScreen.tsx
import { Text } from "@expo/ui/swift-ui";
export function TodayScreen() {
return <Text>Today Screen</Text>;
}
ここでは Today Screen と表示して、Today画面が開いていることを確認できるようにしています。
Tasks画面
src/screens/TasksScreen.tsx
import { Text } from "@expo/ui/swift-ui";
export function TasksScreen() {
return <Text>Tasks Screen</Text>;
}
Tasks 画面も同じ構成です。
今後、この画面に入力フォームやタスク一覧を追加していきます。
Settings画面
src/screens/SettingsScreen.tsx
import { Text } from "@expo/ui/swift-ui";
export function SettingsScreen() {
return <Text>Settings Screen</Text>;
}
Settings 画面も、まずは画面名だけを表示します。
第10回以降で、フォームや選択UIを追加していきます。
補足: なぜ各画面をHostで囲まないのか
ここで、各画面ファイルを Host で囲っていないことに疑問を持つかもしれません。
第2回では、Host の中に Text を置きました。
そのため、TodayScreen、TasksScreen、SettingsScreen でも同じように Host で囲いたくなります。
ただ、今回はこのあと src/app/index.tsx で TabView 全体を Host で囲みます。
<Host style={{ flex: 1 }}>
<TabView defaultSelection="today">
...
</TabView>
</Host>
この構成では、TabView の中に表示される TodayScreen、TasksScreen、SettingsScreen も、すでに Host の内側に入っています。
そのため、各画面ファイル側でさらに Host を重ねる必要はありません。
この教材では、SwiftUI component を表示する入口を src/app/index.tsx の Host にまとめます。
各画面ファイルでは、Text や VStack など、画面の中身だけを書く方針にします。
Step 2: TabViewで3画面を切り替える
src/app/index.tsx で TabView を表示します。
import { Host, TabView } from "@expo/ui/swift-ui";
import { SettingsScreen } from "../screens/SettingsScreen";
import { TasksScreen } from "../screens/TasksScreen";
import { TodayScreen } from "../screens/TodayScreen";
export default function Index() {
return (
<Host style={{ flex: 1 }}>
<TabView defaultSelection="today">
<TabView.Tab value="today" label="Today" systemImage="calendar">
<TodayScreen />
</TabView.Tab>
<TabView.Tab value="tasks" label="Tasks" systemImage="checklist">
<TasksScreen />
</TabView.Tab>
<TabView.Tab value="settings" label="Settings" systemImage="gearshape">
<SettingsScreen />
</TabView.Tab>
</TabView>
</Host>
);
}
Host の中に TabView を置きます。
TabView の中には TabView.Tab を3つ置きます。
Expo Router の (tabs) ディレクトリを使う構成ではなく、1つの画面内で SwiftUI の TabView を表示する構成です。
TodayのタブにはTodayScreenTasksのタブにはTasksScreenSettingsのタブにはSettingsScreen
を入れています。
この構成にしておくと、第4回以降は src/screens/TodayScreen.tsx、src/screens/TasksScreen.tsx、src/screens/SettingsScreen.tsx をそれぞれ段階的に作れます。
Step 3: iOSで動作確認する
iOS Simulator で起動します。
bunx expo start --ios
以下を確認します。
Todayを開くとToday Screenと表示されるTasksを開くとTasks Screenと表示されるSettingsを開くとSettings Screenと表示されるTabViewで3画面を切り替えられる
今回のポイント
今回のポイントは、画面の中身を作り込むことではありません。
TabView で3画面を切り替える土台を作り、各画面を src/screens/ に分けることです。
この形にしておくと、次回以降は1つずつ画面を作れます。
次回やること
次回から、Today 画面を作っていきます。
まずは Text、Label、VStack、HStack、Spacer を使って、Today の基本レイアウトを作ります。