Drawer Navigator
Drawer Navigator 會在畫面的側邊呈現一個可透過手勢開啟和關閉的導覽抽屜。
這是包裝的 react-native-drawer-layout
。如果您想在沒有 React Navigation 整合的狀況下使用抽屜,請直接使用該函式庫。
安裝
要使用此瀏覽器,請確定您已安裝 @react-navigation/native
及其相依性項(請參閱本指南),然後安裝 @react-navigation/drawer
- npm
- Yarn
- pnpm
npm install @react-navigation/drawer
yarn add @react-navigation/drawer
pnpm add @react-navigation/drawer
接著,您需要安裝並設定抽屜瀏覽器所需的函式庫
-
首先,安裝
react-native-gesture-handler
和react-native-reanimated
。如果您執行的是 Expo 管理的專案,請在您的專案目錄中執行
npx expo install react-native-gesture-handler react-native-reanimated
如果您執行的是裸露 React Native 專案,請在您的專案目錄中執行
- npm
- Yarn
- pnpm
npm install react-native-gesture-handler react-native-reanimated
yarn add react-native-gesture-handler react-native-reanimated
pnpm add react-native-gesture-handler react-native-reanimated
Drawer 支援 Reanimated 1 和最新版本的 Reanimated。如果您想使用最新版本的 Reanimated,請務必按照 安裝指南 設定。
-
要完成安裝
react-native-gesture-handler
,請在您的入口檔案(例如index.js
或App.js
)的最上方加入下述程式碼(請確認它是最上方的程式碼,且前面沒有其他內容)import 'react-native-gesture-handler';
警告如果您為 Android 或 iOS 進行建構,請不要跳過此步驟,否則您的應用程式即使在開發階段執行良好,也可能會在實際環境中崩潰。此步驟不適用於其他平台。
-
如果您使用 Mac 並開發 iOS,您還需要安裝 pods(透過 Cocoapods)才能完成連結。
npx pod-install ios
API 定義
若要使用此抽屜導覽,請從 @react-navigation/drawer
匯入
import { createDrawerNavigator } from '@react-navigation/drawer';
const Drawer = createDrawerNavigator();
function MyDrawer() {
return (
<Drawer.Navigator>
<Drawer.Screen name="Feed" component={Feed} />
<Drawer.Screen name="Article" component={Article} />
</Drawer.Navigator>
);
}
如需完整的使用指南,請參閱 抽屜導覽。
Props
Drawer.Navigator
元件接受下列道具
id
導覽的選用唯一 ID。這可以與 navigation.getParent
搭配使用,在子導覽中參考此導覽。
initialRouteName
在導覽首次載入時要呈現的路線名稱。
screenOptions
導覽中畫面要使用的預設選項。
backBehavior
當在導覽中呼叫 goBack
時,由其控制後續動作。包含按下 Android 裝置上的返回鍵或返回手勢。
它支援下列值
firstRoute
- 回到導覽中定義的第一個畫面(預設)initialRoute
- 如果未傳遞,則返回傳入initialRouteName
道具中的初始畫面,否則使用第一個畫面order
- 返回聚焦畫面之前的已定義畫面history
- 返回導覽器中最後一次瀏覽的畫面;如果多次瀏覽同一畫面,則會從歷史記錄中刪除較舊的項目none
- 不處理返回按鈕
defaultStatus
櫃子的預設狀態 - 預設情況下櫃子是要維持 開啟
還是 關閉
狀態。
當此設定設為 開啟
時,櫃子會從初始呈現開始開啟。通常可以使用手勢或以程式方式將它關閉。但是,當返回時,如果櫃子是關閉的,則會重新開啟。這基本上與櫃子的預設行為相反,在預設行為中,櫃子會從 關閉
開始,返回按鈕會將開啟的櫃子關閉。
detachInactiveScreens
布林值,用來表示是否要從檢視階層中分離非作用中的畫面,以節省記憶體。這能與 react-native-screens 進行整合。預設為 true
。
useLegacyImplementation
是否要使用基於 Reanimated 1 的舊版實作。基於 Reanimated 2 的新實作效能會更好,但你需要額外設定,並且需要與 Flipper 搭配使用 Hermes 進行除錯。
在下列情況下,此設定預設為 true
- 未設定 Reanimated 2
- 應用程式已連線至 Chrome 除錯程式(Reanimated 2 無法與 Chrome 除錯程式搭配使用)
- 應用程式在 Web 上執行
否則,預設為 false
drawerContent
傳回要呈現為櫃子內容的 React 元件的函式,例如,導覽項目
內容元件預設接收下列道具
state
- 導覽器的 導覽狀態。navigation
- 導覽器的導覽物件。descriptors
- 包含抽屜畫面的選項的描述元件物件。可以在descriptors[route.key].options
中存取這些選項。
提供自訂的 drawerContent
抽屜的預設元件可捲動且只包含路由配置中路由的連結。您可以輕鬆覆寫預設元件為抽屜新增標題、頁尾或其他內容。預設內容元件以 DrawerContent
匯出。它會在 ScrollView
中繪製 DrawerItemList
元件。
預設情況下,抽屜是可滾動的,支援帶有缺口的裝置。如果您自訂內容,可以使用 DrawerContentScrollView
自動執行此操作
import {
DrawerContentScrollView,
DrawerItemList,
} from '@react-navigation/drawer';
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
</DrawerContentScrollView>
);
}
若要新增額外的項目至抽屜中,您可以使用 DrawerItem
元件
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
<DrawerItem
label="Help"
onPress={() => Linking.openURL('https://mywebsite.com/help')}
/>
</DrawerContentScrollView>
);
}
DrawerItem
元件接受下列道具
label
(必填):項目的標籤文字。可以是字串,或是傳回 React 元素的函式。例如:({ focused, color }) => <Text style={{ color }}>{focused ? 'Focused text' : 'Unfocused text'}</Text>
。icon
:要為項目顯示的圖示。接受傳回 React 元素的函式。例如:({ focused, color, size }) => <Icon color={color} size={size} name={focused ? 'heart' : 'heart-outline'} />
。focused
:布林值,用來指示是否要將抽屜項目標示為「活動」。onPress
(必填):按下時執行之函式。activeTintColor
:項目處於「活動」狀態時的圖示和標籤顏色。inactiveTintColor
:項目處於「非活動」狀態時的圖示和標籤顏色。activeBackgroundColor
:項目處於「活動」狀態時的背景顏色。inactiveBackgroundColor
:項目處於「非活動」狀態時的背景顏色。labelStyle
:標籤文字
的樣式物件。style
:包裝檢視
的樣式物件。
progress
物件可用於在您的 drawerContent
中執行有趣的動態效果,例如抽屜內容視差移動
function CustomDrawerContent(props) {
const progress = useDrawerProgress();
// If you are on react-native-reanimated 1.x, use `Animated.interpolate` instead of `Animated.interpolateNode`
const translateX = Animated.interpolateNode(progress, {
inputRange: [0, 1],
outputRange: [-100, 0],
});
return (
<Animated.View style={{ transform: [{ translateX }] }}>
{/* ... drawer contents */}
</Animated.View>
);
}
如果您使用 Reanimated 1(請參閱 useLegacyImplementation
),progress
物件是 Reanimated 節點
;否則,它是一個 共用值
。它表示抽屜的動態位置(0 為關閉;1 為開啟)。
請注意,您無法在 drawerContent
內部使用 useNavigation
掛鉤,因為 useNavigation
只在畫面中才可用。您會取得 drawerContent
的 navigation
道具,您可以使用此道具
function CustomDrawerContent({ navigation }) {
return (
<Button
title="Go somewhere"
onPress={() => {
// Navigate using the `navigation` prop that you received
navigation.navigate('SomeScreen');
}}
/>
);
}
若要使用自訂元件,我們需要將它傳入 drawerContent
道具
<Drawer.Navigator drawerContent={(props) => <CustomDrawerContent {...props} />}>
{/* screens */}
</Drawer.Navigator>
選項
可以使用下列 選項 來設定導航員的畫面。可以在 Drawer.navigator
的 screenOptions
道具或 Drawer.Screen
的 options
道具下指定這些選項。
title
可用作 headerTitle
和 drawerLabel
備援的通用標題。
lazy
這個畫面第一次被存取時是否應呈現。預設為 true
。如果您要在初始呈現時呈現畫面,請將它設為 false
。
drawerLabel
字串或函式,給定 { focused: boolean, color: string }
後會傳回 React.Node,以在抽屜側欄中顯示。未定義時,會使用場景 title
。
drawerIcon
函式,給定 { focused: boolean, color: string, size: number }
後會傳回 React.Node,以在抽屜側欄中顯示。
drawerActiveTintColor
抽屜中活躍選項的圖示與標籤顏色。
drawerActiveBackgroundColor
抽屜中活躍選項的背景顏色。
drawerInactiveTintColor
抽屜中未活躍選項的圖示與標籤顏色。
drawerInactiveBackgroundColor
抽屜中未活躍選項的背景顏色。
drawerItemStyle
單一選項的樣式物件,可能包含圖示和/或標籤。
drawerLabelStyle
樣式物件,用於套用在內容區段內的 Text
樣式,此區段會呈現標籤。
drawerContentContainerStyle
ScrollView
內部內容區段的樣式物件。
drawerContentStyle
封裝檢視的樣式物件。
drawerStyle
抽屜元件的樣式物件。您可以在此輸入抽屜的自訂背景顏色或自訂寬度。
<Drawer.Navigator
screenOptions={{
drawerStyle: {
backgroundColor: '#c6cbef',
width: 240,
},
}}
>
{/* screens */}
</Drawer.Navigator>
drawerPosition
選項為 left
或 right
。LTR 語言預設為 left
,RTL 語言預設為 right
。
drawerType
抽屜的類型。它決定抽屜的外觀和動畫。
front
:傳統抽屜,其覆蓋屏幕,並在屏幕後方顯示一個圖層。back
:在滑動時顯示屏幕後方的抽屜。slide
:在滑動時,同時滑動屏幕和抽屜,以顯示抽屜。permanent
:永久抽屜顯示為側邊欄。對於大屏幕上始終顯示抽屜來說非常有用。
預設值:iOS上的slide
,其他平台的front
。
您可以有條件地指定drawerType
,以在大屏幕上顯示永久抽屜,而在小屏幕上顯示傳統抽屜。
import { useWindowDimensions } from 'react-native';
import { createDrawerNavigator } from '@react-navigation/drawer';
const Drawer = createDrawerNavigator();
function MyDrawer() {
const dimensions = useWindowDimensions();
return (
<Drawer.Navigator
screenOptions={{
drawerType: dimensions.width >= 768 ? 'permanent' : 'front',
}}
>
{/* Screens */}
</Drawer.Navigator>
);
}
您也可以根據屏幕尺寸指定其他屬性,例如drawerStyle
,以自訂行為。例如,您可以將其與defaultStatus="open"
結合起來,以形成主從布局。
import { useWindowDimensions } from 'react-native';
import { createDrawerNavigator } from '@react-navigation/drawer';
const Drawer = createDrawerNavigator();
function MyDrawer() {
const dimensions = useWindowDimensions();
const isLargeScreen = dimensions.width >= 768;
return (
<Drawer.Navigator
defaultStatus="open"
screenOptions={{
drawerType: isLargeScreen ? 'permanent' : 'back',
drawerStyle: isLargeScreen ? null : { width: '100%' },
overlayColor: 'transparent',
}}
>
{/* Screens */}
</Drawer.Navigator>
);
}
drawerHideStatusBarOnOpen
設定為true
時,抽屜會在拉出時或為「開啟」狀態時隱藏作業系統狀態欄。
drawerStatusBarAnimation
隱藏狀態欄時的動畫。與hideStatusBar
結合使用。
支援的值
slide
fade
none
這僅在 iOS 上支援。預設值為slide
。
overlayColor
開啟抽屜時顯示在內容檢視上方顏色的圖層。開啟抽屜時,不透明度從0
動畫至1
。
sceneContainerStyle
包裝屏幕內容的元件的樣式物件。
gestureHandlerProps
要傳遞給基礎平移手勢處理常式的屬性。
此功能在 Web 上不受支援。
swipeEnabled
是否可以使用滑動手勢開啟或關閉抽屜。預設值為true
。
Web 上不支援滑動手勢。
swipeEdgeWidth
定義滑動手勢應從內容檢視邊緣何處開始觸發。
此功能在 Web 上不受支援。
swipeMinDistance
開啟抽屜所需的最小滑動距離閾值。
keyboardDismissMode
滑動手勢開始時,是否應關閉鍵盤。預設為 'on-drag'
。設為 'none'
以停用鍵盤處理。
unmountOnBlur
遠離畫面時,此畫面是否應卸載。卸載畫面會重設畫面中的任何本機狀態,以及畫面中嵌套導航器的狀態。預設為 false
。
通常,我們不建議啟用此項屬性,因為使用者不希望在切換畫面時他們的瀏覽記錄消失。如果你啟用此項屬性,請考慮這是否確實能為使用者提供更好的體驗。
freezeOnBlur
布林值,代表是否要阻止非活動畫面重新呈現。預設為 false
。當應用程式頂端執行 react-native-screens
套件的 enableFreeze()
時,預設為 true
。
需要 react-native-screens
版本 >= 3.16.0。
僅支援 iOS 和 Android。
標頭相關選項
你可以在 此處 找到標頭相關選項清單。這些 選項 可以在 Drawer.navigator
的 screenOptions
屬性或 Drawer.Screen
的 options
屬性中指定。你無需直接使用 @react-navigation/elements
就能使用這些選項,它們只是在那個頁面中做了文件說明。
除此之外,抽屜中也支援下列選項
header
自訂標頭,用來取代預設的標頭。
此項選項接受回傳 React 元素的函數作為參數,以顯示為標頭。函數會接收一個物件,其中包含下列屬性
navigation
- 目前畫面的導航物件。route
- 目前畫面的路由物件。options
- 目前畫面的選項layout
- 畫面的尺寸,包含height
和width
屬性。
範例
import { getHeaderTitle } from '@react-navigation/elements';
// ..
header: ({ navigation, route, options }) => {
const title = getHeaderTitle(options, route.name);
return <MyHeader title={title} style={options.headerStyle} />;
};
要在導航器中的所有畫面設定自訂標頭,你可以在導航器的 screenOptions
屬性中指定此選項。
在 headerStyle
中指定 height
如果你的自訂標頭高度與預設標頭高度不同,你可能會因為測量為非同步而看到一些錯誤。明確指定高度將可以避免此類錯誤。
範例
headerStyle: {
height: 80, // Specify the height of your custom header
};
請注意,此樣式預設並未套用至標頭,因為你控制的是自訂標頭的樣式。如果你還要將此樣式套用至你的標頭,請使用屬性中的 options.headerStyle
。
headerShown
是否要顯示或隱藏畫面的標頭。預設會顯示標頭。如果將它設定為 false
,則隱藏標頭。
事件
導覽器可以在特定動作時發出事件。支援的事件包括
drawerItemPress
當使用者在抽屜中按下畫面按鈕時,會引發這個事件。預設在按下抽屜項目時,會有幾種動作
- 如果畫面沒有獲得焦點,按下抽屜項目會讓該畫面獲得焦點
- 如果畫面已經獲得焦點,則會關閉抽屜
要避免預設行為,你可以呼叫 event.preventDefault
React.useEffect(() => {
const unsubscribe = navigation.addListener('drawerItemPress', (e) => {
// Prevent default behavior
e.preventDefault();
// Do something manually
// ...
});
return unsubscribe;
}, [navigation]);
如果你的抽屜內容是自訂的,請確定要發出這個事件。
輔助函式
抽屜導覽器將以下方法新增到導覽 props
openDrawer
開啟抽屜窗格。
navigation.openDrawer();
closeDrawer
關閉抽屜窗格。
navigation.closeDrawer();
toggleDrawer
如果抽屜已關閉,則開啟抽屜窗格,如果已開啟,則關閉抽屜窗格。
navigation.toggleDrawer();
jumpTo
在抽屜導覽器中導覽到現有的畫面。這個方法會接受下列引數
name
- 字串 - 要跳轉到的路由名稱。params
- 物件 - 要傳遞到目的路由的畫面參數。
navigation.jumpTo('Profile', { owner: 'Satya' });
範例
import { createDrawerNavigator } from '@react-navigation/drawer';
const Drawer = createDrawerNavigator();
function MyDrawer() {
return (
<Drawer.Navigator initialRouteName="Feed">
<Drawer.Screen
name="Feed"
component={Feed}
options={{ drawerLabel: 'Home' }}
/>
<Drawer.Screen
name="Notifications"
component={Notifications}
options={{ drawerLabel: 'Updates' }}
/>
<Drawer.Screen
name="Profile"
component={Profile}
options={{ drawerLabel: 'Profile' }}
/>
</Drawer.Navigator>
);
}
檢查抽屜是否開啟
你可以使用 useDrawerStatus
勾子來檢查抽屜是否開啟。
import { useDrawerStatus } from '@react-navigation/drawer';
// ...
const isDrawerOpen = useDrawerStatus() === 'open';
如果你無法使用此勾子,你也可以使用 getDrawerStatusFromState
輔助函式
import { getDrawerStatusFromState } from '@react-navigation/drawer';
// ...
const isDrawerOpen = getDrawerStatusFromState(navigation.getState()) === 'open';
對於類別元件,你可以聆聽 state
事件來檢查抽屜是否開啟或關閉
class Profile extends React.Component {
componentDidMount() {
this._unsubscribe = navigation.addListener('state', () => {
const isDrawerOpen =
getDrawerStatusFromState(navigation.getState()) === 'open';
// do something
});
}
componentWillUnmount() {
this._unsubscribe();
}
render() {
// Content of the component
}
}
將抽屜導覽器嵌套在其他元件中
如果一個抽屜導航嵌套在另外提供一些 UI 的導航中,例如一個分頁導航或堆疊導航,那麼這個抽屜會呈現在這些導航的 UI 之下。抽屜會顯示在分頁標籤下方和堆疊標題下方。您需要讓抽屜導航成為任何導航的父層,讓抽屜顯示在它的 UI 的上方。