
【免费下载链接】autoskillsOne command. Your entire AI skill stack. Installed.项目地址https://gitcode.com/gh_mirrors/au/autoskills点击查看免费下载在 Expo 生态中构建移动端标签导航时expo-router/unstable-native-tabs提供的NativeTabs是打造最佳 iOS 体验的首选方案。本文以 autoskills 仓库中 building-native-ui 技能包的核心参考文档 tabs.md 为主体系统讲解NativeTabs的组件化 API、SDK 54 与 SDK 55 的语法差异、iOS 26 Liquid Glass 新特性以及从 JS Tabs 迁移的完整路径。读完本文你将掌握原生标签栏的声明式写法、图标与徽标配置、安全区域处理、搜索标签集成等全部实战能力并能对照仓库中的技能源码与测试用例验证每一个用法。SDK 兼容性SDK 54 与 SDK 55 的语法分水岭NativeTabs要求SDK 54 及以上推荐 SDK 55。两个大版本之间的 API 形态有显著差异是迁移时最容易踩坑的地方方面SDK 54SDK 55导入方式import { NativeTabs, Icon, Label, Badge, VectorIcon }仅import { NativeTabs }图标Icon sfhouse.fill /NativeTabs.Trigger.Icon sfhouse.fill /标签文本LabelHome/LabelNativeTabs.Trigger.LabelHome/NativeTabs.Trigger.Label徽标Badge9/BadgeNativeTabs.Trigger.Badge9/NativeTabs.Trigger.BadgeAndroid 图标drawable属性md属性Material SymbolsSDK 55 将Icon、Label、Badge全部收敛为NativeTabs.Trigger的子组件形成统一的组件树。文中所有示例默认使用 SDK 55 语法若你在 SDK 54 上运行只需把NativeTabs.Trigger.Icon/Label/Badge替换为独立的Icon、Label、Badge导入即可。基本用法声明式的原生标签栏标签布局通过app/(tabs)/_layout.tsx或直接app/_layout.tsx中的NativeTabs定义。每个标签对应一个NativeTabs.Trigger其name必须与路由名精确匹配含括号import { NativeTabs } from expo-router/unstable-native-tabs; export default function TabLayout() { return ( NativeTabs minimizeBehavioronScrollDown NativeTabs.Trigger nameindex NativeTabs.Trigger.Icon sfhouse.fill mdhome / NativeTabs.Trigger.LabelHome/NativeTabs.Trigger.Label NativeTabs.Trigger.Badge9/NativeTabs.Trigger.Badge /NativeTabs.Trigger NativeTabs.Trigger namesettings NativeTabs.Trigger.Icon sfgear mdsettings / NativeTabs.Trigger.LabelSettings/NativeTabs.Trigger.Label /NativeTabs.Trigger NativeTabs.Trigger name(search) rolesearch NativeTabs.Trigger.LabelSearch/NativeTabs.Trigger.Label /NativeTabs.Trigger /NativeTabs ); }这段代码同时为 iOS 指定了 SF Symbolsf、为 Android 指定了 Material Symbolmd并演示了带徽标、普通、搜索三种 Trigger 形态。在 autoskills 仓库的技能 SKILL.md 中也给出了配套的完整路由结构示例app/_layout.tsx放NativeTabs每个 tab 内再用Stack承载各自页面与导航栈。使用规则四条必须遵守的约定每个标签都必须有对应 Trigger缺少任何一个都会导致路由无法到达NativeTabs.Trigger的name必须与路由名完全一致包括括号例如NativeTabs.Trigger name(search)搜索标签尽量放在列表末尾这样它能与搜索栏自然结合iOS 上搜索栏会与末尾标签联动对常见标签类型使用role属性表达语义标签必须是静态的——不允许在运行时动态增删标签否则会重新挂载导航器并丢失页面状态。平台特性各平台的原生实现NativeTabs之所以优于 JS 实现的Tabs核心在于它直接调用平台自带的标签栏组件iOS 26自动获得 Liquid Glass液态玻璃效果与系统级原生外观Android使用 Material 3 底部导航bottom navigation整体带来更好的性能与更地道的原生手感。这与 building-native-ui 技能包整体遵循 Apple Human Interface Guidelines、优先原生体验的定位一致。Icon 组件SF Symbols 与 Material Symbols 双端配置NativeTabs.Trigger.Icon支持以下配置方式// SF Symbol (iOS) Material Symbol (Android) NativeTabs.Trigger.Icon sfhouse.fill mdhome / // 状态变体未选中/选中使用不同符号 NativeTabs.Trigger.Icon sf{{ default: house, selected: house.fill }} mdhome / // 自定义图片 NativeTabs.Trigger.Icon src{require(./icon.png)} / // Xcode asset catalog —— 仅 iOSSDK 55 NativeTabs.Trigger.Icon xcassethome-icon / NativeTabs.Trigger.Icon xcasset{{ default: home-outline, selected: home-filled }} / // 渲染模式 —— 仅 iOSSDK 55 NativeTabs.Trigger.Icon src{require(./icon.png)} renderingModetemplate / NativeTabs.Trigger.Icon src{require(./gradient.png)} renderingModeoriginal /renderingMode的语义template会应用 tint 颜色适用于单色图标original保留源图颜色适用于渐变等多彩素材Android 端始终按 original 处理。关于图标库选型技能包的态度非常明确优先使用 SF Symbols 而非第三方矢量图标库。参考文档 icons.md 中强调 Never use FontAwesome or Ionicons并在 SKILL.md 的库偏好清单里指定用expo-image的sourcesf:name呈现 SF Symbols。符号命名使用点分记法如square.and.arrow.up常用的导航、媒体、社交、状态类符号清单都可以在 icons.md 中查到。Label 与 Badge文本与徽标// Label NativeTabs.Trigger.LabelHome/NativeTabs.Trigger.Label NativeTabs.Trigger.Label hiddenHome/NativeTabs.Trigger.Label {/* 仅图标的标签 */} // Badge NativeTabs.Trigger.Badge9/NativeTabs.Trigger.Badge NativeTabs.Trigger.Badge / {/* 纯圆点指示器 */}hidden让标签只显示图标Badge不带子元素时退化为一个圆点指示器适合表达有新内容这类弱提示。iOS 26 特性Liquid Glass 与新交互Liquid Glass 标签栏在 iOS 26 上标签栏自动采用 Liquid Glass 外观无需额外配置。滚动时收起NativeTabs minimizeBehavioronScrollDown页面内容向下滚动时标签栏自动收起为内容腾出更多空间这是 iOS 26 的招牌交互之一。搜索标签NativeTabs.Trigger name(search) rolesearch NativeTabs.Trigger.LabelSearch/NativeTabs.Trigger.Label /NativeTabs.Trigger注意搜索标签放在列表末尾体验最佳。rolesearch会让标签栏与搜索功能深度整合具体到页面内部可配合headerSearchBarOptions与useSearchHook 实现搜索状态管理相关完整示例见参考文档 search.md。Role 属性为特殊标签类型提供语义化角色NativeTabs.Trigger namesearch rolesearch / NativeTabs.Trigger namefavorites rolefavorites / NativeTabs.Trigger namemore rolemore /可用角色集合search|more|favorites|bookmarks|contacts|downloads|featured|history|mostRecent|mostViewed|recents|topRated。这些角色会让标签栏获得系统级的位置与行为语义例如在更多入口聚合溢出项。自定义Tint 颜色与动态颜色Tint 颜色NativeTabs tintColor#007AFF为整个标签栏指定主题色。动态颜色iOSLiquid Glass 背景下固定颜色可能显得生硬。使用DynamicColorIOS让颜色随浅色/深色外观自适应import { DynamicColorIOS, Platform } from react-native; const adaptiveBlue Platform.select({ ios: DynamicColorIOS({ light: #007AFF, dark: #0A84FF }), default: #007AFF, }); NativeTabs tintColor{adaptiveBlue}条件标签按需显示 Admin 入口NativeTabs.Trigger nameadmin hidden{!isAdmin} NativeTabs.Trigger.LabelAdmin/NativeTabs.Trigger.Label NativeTabs.Trigger.Icon sfshield.fill mdshield / /NativeTabs.Trigger重要约束不要在标签已经可见后再切换hidden—— 反复切换可见性会重新挂载导航器只应在首次渲染期间决定显隐。同时记住被隐藏的标签无法再被导航到hidden tabs cannot be navigated to。行为选项精细控制点击行为NativeTabs.Trigger namehome disablePopToTop // 点击当前激活标签时不弹回栈顶 disableScrollToTop // 点击当前激活标签时不滚动回顶部 disableAutomaticContentInsets // 放弃自动安全区 insetSDK 55 三个开关分别对应三种原生默认行为按需关闭即可。隐藏标签栏SDK 55通过NativeTabs上的hidden属性可以动态隐藏整个标签栏NativeTabs hidden{isTabBarHidden}{/* triggers */}/NativeTabs适合阅读模式、全屏播放等需要临时收起标签栏的场景。底部附件 BottomAccessorySDK 55NativeTabs.BottomAccessory用于在标签栏上方渲染内容iOS 26典型场景是迷你播放器。它通过usePlacement()在regular与inline两种布局间自适应。关键注意点组件会被同时渲染两份实例regular 与 inline 布局各一份因此状态必须存放在组件外部props、context 或外部 store不能依赖组件内部 state 持久化。import { NativeTabs } from expo-router/unstable-native-tabs; import { useState } from react; import { Pressable, Text, View } from react-native; function MiniPlayer({ isPlaying, onToggle, }: { isPlaying: boolean; onToggle: () void; }) { const placement NativeTabs.BottomAccessory.usePlacement(); if (placement inline) { return ( Pressable onPress{onToggle} SymbolView name{isPlaying ? pause.fill : play.fill} / /Pressable ); } return View{/* full player UI */}/View; } export default function TabLayout() { const [isPlaying, setIsPlaying] useState(false); return ( NativeTabs NativeTabs.BottomAccessory MiniPlayer isPlaying{isPlaying} onToggle{() setIsPlaying(!isPlaying)} / /NativeTabs.BottomAccessory NativeTabs.Trigger nameindex NativeTabs.Trigger.Icon sfhouse.fill mdhome / NativeTabs.Trigger.LabelHome/NativeTabs.Trigger.Label /NativeTabs.Trigger /NativeTabs ); }这里isPlaying状态被提升到TabLayout通过 props 传入两个 MiniPlayer 实例确保两个布局的播放状态始终同步。安全区域处理SDK 55SDK 55 起自动处理安全区域Android内容自动包裹在 SafeAreaView 中处理底部 insetiOS第一个 ScrollView 自动获得contentInsetAdjustmentBehavior。若需按标签关闭自动处理使用disableAutomaticContentInsets并手动管理NativeTabs.Trigger nameindex disableAutomaticContentInsets NativeTabs.Trigger.LabelHome/NativeTabs.Trigger.Label /NativeTabs.Trigger// 在页面内 import { SafeAreaView } from react-native-screens/experimental; export default function HomeScreen() { return ( SafeAreaView edges{{ bottom: true }} style{{ flex: 1 }} {/* content */} /SafeAreaView ); }顺带一提技能包在 SKILL.md 中建议日常开发优先使用ScrollView contentInsetAdjustmentBehaviorautomatic /替代 SafeAreaView 来获得更智能的安全区 inset这与 NativeTabs 的自动处理机制是同一套设计哲学。使用 Vector Icons兜底方案只有在必须使用expo/vector-icons而非 SF Symbols时才这样做import { NativeTabs } from expo-router/unstable-native-tabs; import Ionicons from expo/vector-icons/Ionicons; NativeTabs.Trigger namehome NativeTabs.Trigger.VectorIcon vector{Ionicons} namehome / NativeTabs.Trigger.LabelHome/NativeTabs.Trigger.Label /NativeTabs.Trigger推荐做法优先使用sfmd组合而非矢量图标以获得最原生的观感SDK 55 务必用md属性指定 Android 端使用的 Material Symbols。与 Stack 组合的结构为每个标签内嵌导航栈NativeTabs本身不渲染页面头部。需要导航头部时在每个标签组内嵌套Stack// app/(tabs)/_layout.tsx import { NativeTabs } from expo-router/unstable-native-tabs; export default function TabLayout() { return ( NativeTabs NativeTabs.Trigger name(home) NativeTabs.Trigger.LabelHome/NativeTabs.Trigger.Label NativeTabs.Trigger.Icon sfhouse.fill mdhome / /NativeTabs.Trigger /NativeTabs ); } // app/(tabs)/(home)/_layout.tsx import Stack from expo-router/stack; export default function HomeStack() { return ( Stack Stack.Screen nameindex options{{ title: Home, headerLargeTitle: true }} / Stack.Screen namedetails options{{ title: Details }} / /Stack ); }标签内嵌 Stack是技能包反复强调的架构范式参考文档 route-structure.md 指出头部和标题应设置在每个标签内部的 Stack 中让每个标签拥有独立的头部与独立的历史栈根布局通常不带头部在 tab 布局上设置headerShown: false。若两个标签需要共享页面如详情页i/[id]可使用数组路由(index,search)加unstable_settings锚点配置完整示例见 route-structure.md。自定义 Web 布局原生与 Web 分流NativeTabs面向 iOS/Android。Web 端可借助平台专属文件实现不同布局app/ _layout.tsx # NativeTabs for iOS/Android _layout.web.tsx # Headless tabs for web (expo-router/ui)也可以抽取为组件对components/app-tabs.tsxcomponents/app-tabs.web.tsx。这样移动端享受原生标签栏Web 端使用expo-router/ui的无头标签实现互不干扰。从 JS Tabs 迁移逐行对照迁移前JS Tabsimport { Tabs } from expo-router; Tabs Tabs.Screen nameindex options{{ title: Home, tabBarIcon: ({ color }) IconSymbol namehouse.fill color{color} /, tabBarBadge: 3, }} / /Tabs;迁移后Native Tabsimport { NativeTabs } from expo-router/unstable-native-tabs; NativeTabs NativeTabs.Trigger nameindex NativeTabs.Trigger.LabelHome/NativeTabs.Trigger.Label NativeTabs.Trigger.Icon sfhouse.fill mdhome / NativeTabs.Trigger.Badge3/NativeTabs.Trigger.Badge /NativeTabs.Trigger /NativeTabs;关键差异对照表JS TabsNative TabsTabs.ScreenNativeTabs.Triggeroptions{{ title }}NativeTabs.Trigger.Labeloptions{{ tabBarIcon }}NativeTabs.Trigger.IcontabBarBadge选项NativeTabs.Trigger.Badge基于 Props 的 API基于组件的 API内置头部需要嵌套Stack提供头部限制与约束Android最多 5 个标签Material Design 约束嵌套原生标签不能嵌套在其他原生标签内部标签栏高度无法在程序中测量FlatList 透明问题使用disableTransparentOnScrollEdge修复动态标签标签必须静态运行时变更会重新挂载导航器并丢失状态。Android 键盘处理配置在app.json中配置软键盘布局模式为resize避免键盘遮挡底部标签栏{ expo: { android: { softwareKeyboardLayoutMode: resize } } }常见问题排查清单Android 上图标不显示SDK 55 添加md属性或改用 VectorIcon头部缺失在每个标签组内嵌套一个 StackTrigger 名称不匹配name必须与路由名完全一致包括括号徽标不可见Badge 必须是 Trigger 的子组件而不是属性iOS 18 及更早版本标签栏透明如果页面使用ScrollView或FlatList确保它是页面组件的第一个不透明子元素若必须包在另一个View中该包装层要设置collapsable{false}如果页面不用ScrollView/FlatList则在NativeTabs.Trigger选项里设置disableTransparentOnScrollEdge{true}让标签栏不透明点击标签不能滚动回顶部确认当前激活标签的 Trigger 未设置disableScrollToTop且ScrollView是页面组件的第一个子元素切换标签时头部按钮闪烁确保应用外层包裹了ThemeProvider。针对第 7 点完整修复方案是引入react-navigation/native的主题提供器并跟随系统外观切换主题import { ThemeProvider, DarkTheme, DefaultTheme, } from react-navigation/native; import { useColorScheme } from react-native; import { Stack } from expo-router; export default function Layout() { const colorScheme useColorScheme(); return ( ThemeProvider theme{colorScheme dark ? DarkTheme : DefaultTheme} Stack / /ThemeProvider ); }如果应用只使用单一明/暗主题可以跳过useColorScheme直接传入对应主题import { ThemeProvider, DarkTheme } from react-navigation/native; import { Stack } from expo-router; export default function Layout() { return ( ThemeProvider theme{DarkTheme} Stack / /ThemeProvider ); }在 autoskills 中的定位与使用方式本指南对应的tabs.md是 autoskills 仓库中building-native-ui技能的一部分。该技能在仓库的技能映射 skills-map.ts 中被挂载到expo技术栈下当你的项目package.json中存在expo依赖时autoskills 会自动识别并建议安装该技能技能包的注册信息来源expo/skills、commitSha 与文件清单记录在 skills-registry/index.json安装逻辑的相关测试见 collect.test.ts。你可以在项目根目录运行npx autoskillsNode.js 22它会扫描项目依赖并自动安装匹配的 AI Agent 技能之后 Agent 在编写 Expo 应用时即可参考building-native-ui技能下的 SKILL.md 与全部参考文档其中就包括本文所讲的 tabs.md。技能的其余参考文档图标 icons.md、路由结构 route-structure.md、搜索 search.md、视觉效果 visual-effects.md 等可在同一目录下查阅与本文共同构成一套完整的 Expo 原生 UI 开发指南。赞分享【免费下载链接】autoskillsOne command. Your entire AI skill stack. Installed.项目地址https://gitcode.com/gh_mirrors/au/autoskills点击查看免费下载相关推荐Expo Router NativeTabs 完全指南在 Expo SDK 54/55 上构建原生标签导航Expo Router NativeTabs 完全指南在 Expo SDK 54/55 上构建原生标签导航 本篇技术指南以 AASagentic awesoAI 技能AI 插件expo-glass-effect 深度指南在 Expo 应用中使用 iOS 26 Liquid Glass 原生毛玻璃效果expo glass effect 深度指南在 Expo 应用中使用 iOS 26 Liquid Glass 原生毛玻璃效果 expo glass effec移动开发前端跨平台原生移动Nx 工作区中 Expo SDK 53 升级迁移到 SDK 54 的完整指南Nx 工作区中 Expo SDK 53 升级迁移到 SDK 54 的完整指南 导读本文以 Nx 官方仓库 ai instructions for expo 5开发工具构建工具MonorepoCLI上一篇MemOS 获取建议问题Get Suggestions接口深度解析双模式“猜你想问”实现与实战调用指南下一篇Ekko Studio App Relay 应用连接中继从 LAN 直连到云端中转的完整授权与转发机制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考