iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
Build on Google AI

單鐵的人生如履薄冰!AI 教練 APP 30天開發旅程,你說能走到最後嗎?系列 第 15

Day 15 | 導覽列與路由:實作首頁、課表頁、個人頁面的絲滑切換

  • 分享至 

  • xImage
  •  

前言:單頁 APP 是不夠的,我們需要導覽列!

昨天我們完成了「KAKERU」的第一個首頁畫面。有讀者一定有發現,畫面底部出現了一個非常有質感的黑色懸浮導覽列!

https://ithelp.ithome.com.tw/upload/images/20260824/20165043pQxQHyzZoa.jpg

但目前它只是 AI 幫我們畫出來的「純視覺 UI」,點了並不會有反應。一個 APP 需要讓使用者在不同功能上絲滑的切換。經過架構收斂,我們規劃了黃金三角:

  1. 🏃 首頁 (Home):本週訓練重點與 AI 教練狀態摘要。
  2. 📅 課表 (Schedule):每日訓練菜單與執行進度。
  3. ⚙️ 個人設定 (Profile):跑者基本生理數值與目標賽事。

在 React Native 生態系中,管理頁面切換的是 React Navigation(亦為 Expo 路由底層)。今天將透過下 Prompt 建立路由骨架,並排解實務上常見的介面重疊問題。

觀念轉換:Web 的 URL vs. App 的 Navigation

  • Web 是「網址導向 (URL-based)」:換網址即換頁,舊頁面隨之銷毀。
  • App 是「圖層導向 (Layer & State-based)」
    • Stack (堆疊):點擊下一頁時,新頁面像卡片「覆蓋」在舊頁面上;返回即抽除。
    • Tabs (分頁):底部導覽列,各分頁「平行並存」,切換時保留各自的輸入與滾動狀態。

動手實作 1:詢問 Expo 原生相容安裝指令

我們請 AI 提供符合 Expo 環境的精準安裝指令:

「我正在使用 React Native + Expo 開發 APP。 我想要實作底部導覽列。請給我 React Navigation 最新版的完整安裝指令。注意:請給我符合 Expo 環境的安裝方式 (使用 npx expo install) 來處理原生依賴。」

# 1. 安裝核心套件
npm install @react-navigation/native

# 2. 透過 Expo 安裝原生依賴 (避免版本衝突)
npx expo install react-native-screens react-native-safe-area-context

# 3. 安裝 Bottom Tabs 套件
npm install @react-navigation/bottom-tabs

動手實作 2:生成三大分頁路由骨架

接著,請 AI 把 Day 14 的單頁架構,升級為包含三個分頁的正式路由:

「幫我用 React Navigation 寫一個帶有 Bottom Tabs 導覽列的路由設定。
設計需求:

  1. 三個平行分頁:首頁 (HomeScreen)、課表 (ScheduleScreen)、個人設定 (ProfileScreen)。
  2. Tab 標籤名稱請使用繁體中文:『首頁』、『課表』、『設定』。
  3. Active 顏色使用品牌亮橘色 (#FF5722),Inactive 使用灰色 (#9CA3AF)。
  4. 頂部標題列需隱藏 (headerShown: false)。
  5. 課表與設定頁面先建立置中的 SafeAreaView 佔位元件。」

產出程式碼

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

// 引入 Day 14 實作之首頁
import HomeScreen from './src/screens/HomeScreen';

function ScheduleScreen() {
  return (
    <SafeAreaView style={styles.center}>
      <Text style={styles.icon}>📅</Text>
      <Text style={styles.title}>訓練課表</Text>
      <Text style={styles.subtitle}>AI 教練將在此規劃每日專屬訓練菜單</Text>
    </SafeAreaView>
  );
}

function ProfileScreen() {
  return (
    <SafeAreaView style={styles.center}>
      <Text style={styles.icon}>⚙️</Text>
      <Text style={styles.title}>個人設定</Text>
      <Text style={styles.subtitle}>即將於 Day 16 實作跑者生理數據與賽事目標表單</Text>
    </SafeAreaView>
  );
}

const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions={{
          tabBarActiveTintColor: '#FF5722',
          tabBarInactiveTintColor: '#9CA3AF',
          headerShown: false,
        }}
      >
        <Tab.Screen name="Home" component={HomeScreen} options={{ tabBarLabel: '首頁' }} />
        <Tab.Screen name="Schedule" component={ScheduleScreen} options={{ tabBarLabel: '課表' }} />
        <Tab.Screen name="Profile" component={ProfileScreen} options={{ tabBarLabel: '設定' }} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

const styles = StyleSheet.create({
  center: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F4F5F7',
    paddingHorizontal: 24,
  },
  icon: { fontSize: 48, marginBottom: 16 },
  title: { fontSize: 24, fontWeight: '800', color: '#1A1D20', marginBottom: 8 },
  subtitle: { fontSize: 15, color: '#6B7280', textAlign: 'center' },
});

實戰遭遇:排除導覽列與首頁按鈕的重疊衝突

當我們存檔並在手機上預覽時,發現了一個真實開發中的 UI/UX 問題:
https://ithelp.ithome.com.tw/upload/images/20260824/20165043PA4bdSFTps.png

問題點分析

  1. 視覺重疊:首頁底部的橘色大按鈕,直接被懸浮的導覽列遮住。
  2. 語意重複:底部導覽列已經有「課表」分頁,首頁下方又放一顆滿版的「查看課表」按鈕,造成功能重複。

再請AI幫我們修復問題:

「我在首頁加入了底部導覽列後,發現首頁原本底部的按鈕與浮動導覽列重疊了,且功能跟導覽列的『課表』重複。 請幫我重構首頁的排版:
將中間的『本週訓練重點』卡片改為可點擊跳轉至課表。
底部按鈕文案改為『開始今日訓練』,並加上適當的底部間距 (paddingBottom),使其優雅地置於導覽列上方。」

修正成果
https://ithelp.ithome.com.tw/upload/images/20260824/20165043CBx60wkxYg.png

架構審查

  1. <NavigationContainer>:App 路由總管,所有分頁與切換行為皆需包覆在此容器內。
  2. headerShown: false:關閉預設頂部 Header,將視覺設計主導權留給各個頁面。
  3. 安全邊界 (Bottom Inset):這也是今天學到的一課!當使用浮動式 (Absolute Position) 或較高的自訂 Tab Bar 時,底層頁面的容器必須預留足夠的 paddingBottom,才不會發生按鈕或文字被永遠壓在導覽列底下的慘劇。

今日總結與明日預告

今天透過 Prompt 快速完成了 React Navigation 路由架構,為 AI 生成的靜態介面注入了靈活切換的靈魂,並且在遇到真實的畫面重疊時,漂亮地調整了 UI 佈局與安全邊距!

現在,三大功能分頁的骨架已全部完成!明天(Day 16)將正式進入「設定」頁面:實作跑者身高、體重與目標賽事輸入表單,為後續串接 AI 產出客製化課表,準備好最關鍵的參數!

爛笑話角落

:「欸,我昨天開車去小巨蛋聽 back number 現場,發現車位真的超小、超難停。我剛剛在外面倒車倒了半天都進不去,差點擦撞。」
友人:「真假!小巨蛋捷運可以到,不然你下次可以考慮。」
:「對啊,不然我還在想,在這種地方倒車…真的很難」
:「bakuu 難吧」(bakuu 台語)(number 日語) -> (バックナンバー) 中文唸巴哭難吧
友人:…跟你聊天才難…

:開玩笑的啦~我沒車,沒有倒車難吧的問題,但聽 back number 還是可以推一下!歡迎大家去聽!


上一篇
Day 14 | React Native 核心觀念轉換:從 Web 元件思維走向跨平台 Mobile APP
系列文
單鐵的人生如履薄冰!AI 教練 APP 30天開發旅程,你說能走到最後嗎?15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言