用 expo-native-ui 讓 AI 寫出更像原生 App 的 Expo 界面

前言

用 Cursor、Claude Code 這類 AI 編程工具寫 Expo / React Native 界面時,常見情況是:功能能跑,但觀感像「套了一層 Web」——顏色寫死成 hex、陰影還在用舊的 shadow* / elevation、安全區靠猜、動畫隨便上一套 Animated。模型並不缺組件名,缺的是一套和當前 Expo SDK 對齊的原生 UI 約定。

Expo 官方把這類約定收成了 Agent Skill。其中 expo-native-ui 專門管「屏幕長什麼樣」:語義色、原生控件、SF Symbols、動畫、模糊與漸變、本地存儲與響應式佈局。路由、Tabs、Modal 等導航則交給同倉庫裏的 expo-router Skill。官方文檔給出的典型提示是:「Build a settings screen with native-feeling controls」,代理會自動匹配到 expo-native-ui

本文基於 Expo 官方倉庫 expo/skillsexpo-native-uiSKILL.md(版本 1.1.1,MIT)以及 docs.expo.dev/skills 的安裝說明整理,說明它是什麼、裝在哪裏、以及讓 AI 按這套規範寫界面時要注意什麼。

這是什麼

expo-native-ui 是 Expo 團隊維護的 Framework(開源) 類 Skill,屬於 expo/skills 插件裏的免費 SDK 技能之一。它不是一個 npm UI 庫,而是一份給 AI Agent 讀的結構化說明(SKILL.md + references/),告訴代理在 Expo 項目裏如何搭出「原生感」更強的屏幕。

官方描述可以概括爲:按 Apple Human Interface Guidelines 做樣式;用語義色、原生控件、SF Symbols、媒體、動畫、視覺效果、漸變、存儲和響應式佈局,構建觀感接近系統 App 的 Expo 界面。導航相關需求應改用 expo-router Skill。

Skill 目錄下還掛了若干按需查閱的參考文檔,例如:

references/
  animations.md      Reanimated:進入/退出、佈局、滾動驅動、手勢
  controls.md        原生控件:Switch、Slider、SegmentedControl、DateTimePicker、Picker
  gradients.md       CSS 漸變(experimental_backgroundImage,需 New Architecture)
  icons.md           通過 expo-image 的 sf: 源使用 SF Symbols
  media.md           相機、音頻、視頻與文件保存
  storage.md         SQLite、AsyncStorage、SecureStore
  visual-effects.md  模糊(expo-blur)與 liquid glass(expo-glass-effect)
  webgpu-three.md    WebGPU / Three.js 三維與 GPU 可視化

核心約定與亮點

下面這些點都直接寫在官方 SKILL.md 裏,也是它和「隨便讓 AI 寫 RN」差別最大的地方。

1、先用 Expo Go,再考慮自定義構建

Skill 把這一點標成 CRITICAL:多數 Expo 應用不需要自定義原生代碼。流程是先 npx expo start,用 Expo Go 掃碼驗證;只有本地 Expo Module、Apple Targets(如 widget / App Clip)、Expo Go 未收錄的第三方原生模塊,或 app.json 表達不了的原生配置,才需要 npx expo run:ios/androideas build

這能減少 AI 一上來就跑本地原生構建、拖慢迭代的情況。

2、庫與 API 偏好(避免過時寫法)

Skill 明確要求代理遵守一批「用這個、別用那個」:

  • 不要用已從 React Native 移除的模塊(如舊版 Picker、WebView、SafeAreaView、AsyncStorage 等內置用法)
  • 不要用已廢棄的 expo-permissions
  • 音視頻用 expo-audio / expo-video,不要再用 expo-av
  • SF Symbols 用 expo-imagesource="sf:name",不要用 expo-symbols@expo/vector-icons 湊合
  • 安全區用 react-native-safe-area-context,不用 RN 內置 SafeAreaView
  • 平臺判斷優先 process.env.EXPO_OS,而不是 Platform.OS
  • 語義色用 expo-routerColor API,而不是手寫 PlatformColor
  • SDK 56+ 不要直接從 @react-navigation/* 導入,改走 expo-router/react-navigation

樣式側還要求:跟 Apple HIG;優先 flex gap;圓角用 { borderCurve: 'continuous' };陰影用 CSS 風格的 boxShadow,不要再用舊的 shadow / elevation;不支持 CSS / Tailwind(需要 Tailwind 時應走單獨的 expo-tailwind-setup Skill)。

3、語義色:一套可隨系統明暗變化的 palette

官方示例把顏色集中在 theme/colors.ts,用 Color(來自 expo-router)包一層 Platform.select,併爲 Web 提供 default 十六進制回退:

// theme/colors.ts
import { Platform } from "react-native";
import { Color } from "expo-router";

export const colors = {
  label: Platform.select({
    ios: Color.ios.label,
    android: Color.android.dynamic.onSurface,
    default: "#000000",
  })!,
  secondaryLabel: Platform.select({
    ios: Color.ios.secondaryLabel,
    android: Color.android.dynamic.onSurfaceVariant,
    default: "#3c3c43",
  })!,
  systemBackground: Platform.select({
    ios: Color.ios.systemBackground,
    android: Color.android.dynamic.surface,
    default: "#ffffff",
  })!,
  systemBlue: Platform.select({
    ios: Color.ios.systemBlue,
    android: Color.android.dynamic.primary,
    default: "#007aff",
  })!,
};

頁面裏直接引用 colors.labelcolors.systemBackground 即可。注意:不要把 Color / PlatformColor 傳進 Reanimated 樣式,動畫裏要用靜態顏色(references/animations.md 也寫了這一點)。

4、動畫默認走 Reanimated

references/animations.md 要求使用 Reanimated v4,避免 React Native 內置 Animated。進入/退出可用 FadeIn / FadeOut,佈局變化可用 LinearTransition

import Animated, {
  FadeIn,
  FadeOut,
  LinearTransition,
} from "react-native-reanimated";

function App() {
  return (
    <Animated.View
      entering={FadeIn}
      exiting={FadeOut}
      layout={LinearTransition}
    />
  );
}

同文件還覆蓋滾動驅動動畫、手勢拖拽、鍵盤高度聯動、列表錯峯進入等模式,並建議交互動畫儘量控制在 300ms 內、優先用 transform 而不是改寬高。

5、原生控件與觸感

references/controls.md 偏向系統控件:SwitchSegmentedControlSliderDateTimePickerPicker 等。Switch、DateTimePicker 自帶 haptics,Skill 提醒不要再疊一層多餘震動;分段控件最多約 4 項、文案儘量短,顏色儘量別亂改,好讓暗色模式跟着系統走。

安裝與啓用

expo-native-ui 隨整個 Expo Skills 套件分發。安裝方式按 AI 工具區分(官方 README 與 docs.expo.dev/skills 一致)。

Claude Code

從官方插件市場安裝 Expo 插件:

claude plugin install expo@claude-plugins-official

也可以在 Claude Code 裏執行:

/plugin install expo@claude-plugins-official

Codex

codex plugin add expo@openai-curated

或在 Codex 中打開 /plugins,從 OpenAI-curated marketplace 安裝 expo

Cursor 及其他 Agent

若尚未安裝,在項目根目錄用 skills CLI

# npm
npx skills add expo/skills

# yarn
yarn dlx skills add expo/skills

# pnpm
pnpm dlx skills add expo/skills

# bun
bunx skills add expo/skills

倉庫 README 也給出等價寫法,可一次裝入全部 Expo Skills,並可選指定單個 Skill:

npx skills@latest add expo/skills --skill '*'

只裝本篇相關 Skill 時,可把 --skill 換成 expo-native-ui(CLI 仍可能詢問安裝到哪個 Agent)。裝完後重啓或刷新 Agent 會話,讓它重新發現 SKILL.md

Cursor 側:打開 Settings → Rules, Skills, Subagents,確認 Include third-party Plugins, Skills, and other configs 已開啓,在 Skills 列表裏能看到 Expo Skills。官方說明:Cursor 的 Skills 不會出現在 / 斜槓菜單裏,而是在你提 Expo 相關需求時由代理自動匹配。

更新(skills CLI 安裝路徑):

npx skills@latest update

或更新單個 Skill,例如:

npx skills@latest update expo-router

Claude Code / Codex 的插件安裝則走各自 marketplace 的更新機制。

典型用法

安裝後不必手動「調用」某個命令;用自然語言描述界面需求即可。官方文檔列出的示例提示:

Build a settings screen with native-feeling controls

README 裏還有更貼近整屏搭建的說法:

Build a native-feeling Expo Router screen with tabs, modals, and animations.

後一種往往會同時觸發 expo-router(導航結構)和 expo-native-ui(樣式、控件、動畫)。實際協作時可以寫得更具體,例如:

用 Expo Router 做一個設置頁:分組開關、分段控件、日期選擇;
顏色走 expo-router 的 Color 語義色;開關用系統 Switch;
列表項進入用 Reanimated FadeIn;先在 Expo Go 裏驗證,不要一上來自定義原生構建。

代理按 Skill 工作時,通常會:優先 Expo Go;用語義色與 boxShadow;控件選原生組件;動畫走 Reanimated;文件名用 kebab-case(如 comment-card.tsx);路由標題用導航棧 title,而不是頁面裏再手寫一個大標題。

適用場景與注意事項

比較適合:

  • 用 AI 在 Expo 項目裏搭設置頁、列表頁、詳情頁等「系統感」界面
  • 希望輸出統一遵守 HIG、語義色、安全區、Reanimated 等約定,減少過時 API
  • 已裝或準備裝 expo-router,需要把「導航」和「視覺/交互」分工給不同 Skill

需要注意:

  • 它教的是 Agent 怎麼寫 Expo UI,不是替代 Expo 文檔 / Expo CLI / EAS CLI;源碼與命令仍以官方文檔爲準
  • expo-ui 不同:後者面向 @expo/ui(SwiftUI / Jetpack Compose 那一套);expo-native-ui 更偏 React Native 組件 + Expo SDK 的原生觀感約定
  • CSS / Tailwind 不在本 Skill 範圍內;需要 Tailwind v4 / NativeWind v5 時用 expo-tailwind-setup
  • 漸變參考裏提到的 experimental_backgroundImage 依賴 New Architecture,項目架構不匹配時不要強行照抄
  • 發現 Skill 內容過時或誤導時,官方提供反饋命令(需具體、可操作):
npx --yes submit-expo-feedback@latest --category skills --subject "expo-native-ui" "<actionable feedback>"

小結

expo-native-ui 把「怎樣寫出更像原生的 Expo 屏幕」寫成可被 Cursor、Claude Code、Codex 等 Agent 自動加載的 Skill:語義色、原生控件、Reanimated、安全區與陰影約定、以及先 Expo Go 後自定義構建的流程,都寫在官方 SKILL.mdreferences/ 裏。裝上 Expo Skills 之後,用一句「做有原生感的設置頁」往往就能對上這套規範。

官方地址:

  • Skill 目錄:https://github.com/expo/skills/tree/main/plugins/expo/skills/expo-native-ui
  • 倉庫總覽:https://github.com/expo/skills
  • 安裝與技能列表:https://docs.expo.dev/skills
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜