具有巢狀導覽器的畫面的選項
在本文件中,我們將說明當有多個導覽器時,畫面選項如何運作。了解此概念很重要,如此一來您才能將 options
放置在正確的地方,並妥善組態您的導覽器。如果你把他們放在錯誤的地方,最好的情況是什麼都不會發生,最糟糕的情況是會發生一些令人困惑且意外的事情。
您只能從它的其中一個畫面元件修改導覽器的導覽選項。這同樣適用於巢狀為畫面的導覽器。
舉例來說,一個在每個分頁中包含原生堆疊的標籤導覽器。如果我們在其堆疊內的畫面中設定 options
會怎樣?
const Tab = createTabNavigator();
const HomeStack = createNativeStackNavigator();
const SettingsStack = createNativeStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen
name="A"
component={A}
options={{ tabBarLabel: 'Home!' }}
/>
</HomeStack.Navigator>
);
}
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen
name="B"
component={B}
options={{ tabBarLabel: 'Settings!' }}
/>
</SettingsStack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
正如前面提到的,您只能從一個螢幕元件修改其導覽選項。以上的 A
和 B
分別是 HomeStack
和 SettingsStack
中的螢幕元件,而不在分頁導覽列中。因此,結果將是 tabBarLabel
屬性並未套用至分頁導覽列。不過,我們可以解決!
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen
name="Home"
component={HomeStackScreen}
options={{ tabBarLabel: 'Home!' }}
/>
<Tab.Screen
name="Settings"
component={SettingsStackScreen}
options={{ tabBarLabel: 'Settings!' }}
/>
</Tab.Navigator>
</NavigationContainer>
);
}
當我們直接在包含 HomeStack
和 SettingsStack
元件的 Screen
元件設定 options
時,此設定讓我們可以在將其用作螢幕元件時控制其父導覽列的選項。本例中,我們的堆疊元件上的選項會配置用於呈現堆疊的分頁導覽列中的標籤。
根據子導覽列的狀態設定父螢幕選項
想像以下設定
const Tab = createBottomTabNavigator();
function HomeTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={FeedScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
<Tab.Screen name="Account" component={AccountScreen} />
</Tab.Navigator>
);
}
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeTabs} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
如果我們要使用 options
為 FeedScreen
設定 headerTitle
,這將無法作用。這是因為 App
堆疊僅會在它的直接子代中尋找設定:HomeTabs
和 SettingsScreen
。
不過,我們可以根據分頁導覽列的導覽狀態使用 getFocusedRouteNameFromRoute
輔助函式判斷 headerTitle
選項。我們先建立一個函式來取得標題
import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
function getHeaderTitle(route) {
// If the focused route is not found, we need to assume it's the initial screen
// This can happen during if there hasn't been any navigation inside the screen
// In our case, it's "Feed" as that's the first screen inside the navigator
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Feed';
switch (routeName) {
case 'Feed':
return 'News feed';
case 'Profile':
return 'My profile';
case 'Account':
return 'My account';
}
}
然後我們就可以在 Screen
上使用 options
prop 搭配這個函式
<Stack.Screen
name="Home"
component={HomeTabs}
options={({ route }) => ({
headerTitle: getHeaderTitle(route),
})}
/>
所以這裡發生了什麼事呢?藉由使用 getFocusedRouteNameFromRoute
輔助函式,我們可以從這個子導覽列(本例中是分頁導覽列,因為這是我們要呈現的)取得目前作用中的路線名稱,然後為標題設定一個適當的標題。
只要您想要根據子導覽列的狀態為父導覽列設定選項,就可以隨時使用這種方法。常見的使用案例有
- 在堆疊標題列中顯示分頁標題:堆疊中包含一個分頁導覽列,您想在堆疊標題列中設定標題(以上的範例)
- 在沒有分頁導覽列的情況下顯示螢幕:分頁導覽列中包含一個堆疊,而且您想要在特定的螢幕上隱藏分頁導覽列(不建議這麼做,請參閱在特定螢幕隱藏分頁導覽列)
- 在某些螢幕上鎖定抽屜:抽屜裡面有一個堆疊,而且您想要在某些螢幕上鎖定抽屜
在許多情況下,我們可以透過重新整理導覽列來達到類似的效果。如果符合您的使用案例,我們通常建議使用這個選項。
例如,對於上面的使用案例,我們可以將堆疊導覽列新增至每個分頁中,而非在堆疊導覽列中新增分頁導覽列。
const FeedStack = createNativeStackNavigator();
function FeedStackScreen() {
return (
<FeedStack.Navigator>
<FeedStack.Screen name="Feed" component={FeedScreen} />
{/* other screens */}
</FeedStack.Navigator>
);
}
const ProfileStack = createNativeStackNavigator();
function ProfileStackScreen() {
return (
<ProfileStack.Navigator>
<ProfileStack.Screen name="Profile" component={ProfileScreen} />
{/* other screens */}
</ProfileStack.Navigator>
);
}
const Tab = createBottomTabNavigator();
function HomeTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={FeedStackScreen} />
<Tab.Screen name="Profile" component={ProfileStackScreen} />
</Tab.Navigator>
);
}
const RootStack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<RootStack.Navigator>
<RootStack.Screen name="Home" component={HomeTabs} />
<RootStack.Screen name="Settings" component={SettingsScreen} />
</RootStack.Navigator>
</NavigationContainer>
);
}
此外,這可以讓您將新螢幕推送到 feed 和設定檔堆疊,而不會透過新增更多路由到這些堆疊中來隱藏分頁導覽列。
如果要將畫面推至分頁標籤列上方(即不顯示分頁標籤列),則你可以將它們新增至 App
堆疊,而不是將它們新增至分頁導覽器內的畫面中。