跳到主要內容
版本:6.x

堆疊導航器

堆疊導航器提供一種方式,讓您的應用程式可在畫面之間切換,每個新畫面都會置於堆疊的頂端。

預設情況下,堆疊導航器會設定為具備常見的 iOS 和 Android 外觀及觸感:在 iOS 上,新的畫面從右側滑入,在 Android 上,使用 OS 預設動畫。但是,動畫可以依據您的需求自訂

有一點需要注意,雖然 @react-navigation/stack 擁有極高的可自訂性,但它是以 JavaScript 實作。雖然它使用原生方式執行動畫和手勢,但效能可能不如原生實作。這可能對許多應用程式來說不是問題,但如果您在導航時遇到效能問題,請考慮改用 @react-navigation/native-stack - 它使用原生導航基本項目。

安裝

如要使用此導航器,請確保您擁有 @react-navigation/native 及其依賴項(參閱此指南),然後安裝 @react-navigation/stack

npm install @react-navigation/stack

接著,您需要安裝並設定堆疊導航器所需的函式庫

  1. 首先,安裝 react-native-gesture-handler

    如果您有 Expo 管理的專案,請在專案目錄中執行

    npx expo install react-native-gesture-handler

    如果您有一個空白 React Native 專案,請在您專案目錄中執行

    npm install react-native-gesture-handler
  2. 若要完成安裝 react-native-gesture-handler,請在您的輸入檔案(例如 index.jsApp.js)的最上方新增下列內容(請確定它在最上方,且前面沒有其他內容)

    import 'react-native-gesture-handler';
    警告

    如果您要建置 Android 或 iOS 的版本,請勿跳過此步驟,否則您的應用程式可能會在生產環境中崩潰,即使它在開發環境中運作良好。此步驟不適用於其他平台。

  3. 另外,您也可以安裝 @react-native-masked-view/masked-view。如果您想對頁首使用 UIKit 造型動畫,則需要這個套件(HeaderStyleInterpolators.forUIKit)。

    如果您有 Expo 管理的專案,請在專案目錄中執行

    npx expo install @react-native-masked-view/masked-view

    如果您有一個空白 React Native 專案,請在您專案目錄中執行

    npm install @react-native-masked-view/masked-view
  4. 如果您是在 Mac 上開發 iOS 版本,您也需要透過 Cocoapods 來安裝 pods 以完成連結。

npx pod-install ios

API 定義

若要使用這個導航器,請從 @react-navigation/stack 匯入它

import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Notifications" component={Notifications} />
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
);
}

屬性

Stack.Navigator 組件接受下列屬性

id

導航器的選用唯一 ID。可搭配 navigation.getParent 使用,以便在子導航器中參考這個導航器。

initialRouteName

導航器首次載入時要呈現的路線名稱。

screenOptions

導航器中螢幕要使用的預設選項。

detachInactiveScreens

布林值,用來表示是否要從檢視階層中分離非活動的螢幕以節省記憶體。這可協助整合 react-native-screens。預設為 true

如果您需要針對特定螢幕停用這個最佳化(例如當一個螢幕失去焦點時,您仍希望它繼續顯示),請使用 detachPreviousScreen 選項。

選項

下列 選項 可用於配置導覽器中的畫面。它們可以用 Stack.navigator 屬性的 screenOptions 屬性或 Stack.Screen 屬性的 options 屬性指定。

title

可供作為 headerTitle 替換的字串。

cardShadowEnabled

使用此屬性可在過場動畫期間顯示陰影。預設為 true

cardOverlayEnabled

使用此屬性可在過場動畫期間在卡片下方顯示半透明的深色覆蓋層。預設為 Android 的 true 和 iOS 的 false

cardOverlay

回傳 React 元素作為卡片覆蓋層顯示的函數。請務必在使用時將 cardOverlayEnabled 設為 true

cardStyle

堆疊中卡片的樣式物件。你可以在此處提供自訂的背景色彩,以取代預設的背景顏色。

你也可以指定 { backgroundColor: 'transparent' },以讓前一個畫面在下面顯示(適用於透明的對話方塊)。這對於實作諸如模組化對話方塊之類的功能非常實用。當使用透明背景時,你也應該在選項中指定 presentation: 'modal',這樣前一個畫面才不會分離,且會繼續顯示在下方。

在 Web 上,畫面的高度不受視窗高度的限制。此設計的目的是讓瀏覽器的網址列在捲動時自動隱藏。如果你不想要此行為,你可以將 cardStyle 設為 { flex: 1 },以強制畫面填滿視窗。

presentation

これは、レンダリングやトランジションのスタイルを構成するための複数のオプションを構成するショートカットオプションです。

  • card: iOS と Android 画面のトランジションに OS の既定のアニメーションを使用します。
  • modal: モーダルアニメーションを使用します。これにより、いくつかのことが変更されます。
    • 別に指定されていない限り、画面の headerModescreen に設定します。
    • モーダルのプラットフォームの動作に一致するように画面アニメーションを変更します。
  • transparentModal: modal と似ています。次のことを変更します。
    • 別に指定されていない限り、画面の headerModescreen に設定します。
    • 画面の背景色を透明に設定し、前の画面が見えるようにします。
    • 前の画面がレンダリングされた状態のままになるように detachPreviousScreen オプションを調整します。
    • 前の画面が最後の位置からアニメーションすることを防止します。
    • 画面アニメーションを垂直スライドアニメーションに変更します。

transparentModal のカスタマイズ方法の詳細については、透明モーダル を参照してください。

animationEnabled

是否在螢幕上啟用轉場動畫。如果您將它設定為 false,螢幕在 push 或 pop 時不會執行動畫。iOS 和 Android 預設為 true,網路則為 false

animationTypeForReplace

當這個螢幕取代另一個螢幕時要使用的動畫類型。它採用下列值

  • push - 將使用新螢幕被 push 進來的動畫
  • pop - 將使用螢幕被 pop 出去的動畫

預設為 push

當使用 pop 時,pop 動畫會套用在被取代的螢幕。

gestureEnabled

是否可以使用手勢關閉這個螢幕。iOS 預設為 true,Android 預設為 false

網路不支援手勢。

gestureResponseDistance

覆寫從螢幕邊緣觸控開始的距離以識別手勢的數字。

它會根據 gestureDirection 值設定水平或垂直距離。

預設值為

  • 50 - 當 gestureDirectionhorizontalhorizontal-inverted
  • 135 - 當 gestureDirectionverticalvertical-inverted

此功能在網路上不受支援。

gestureVelocityImpact

決定手勢速度相關性的數字。預設為 0.3。

此功能在網路上不受支援。

gestureDirection

手勢的方向。請參閱 動畫區段 以取得詳細資訊。

此功能在網路上不受支援。

transitionSpec

螢幕轉場的設定物件。請參閱 動畫區段 以取得詳細資訊。

cardStyleInterpolator

卡片各種組成部分的內插樣式。請參閱 動畫區段 以取得詳細資訊。

headerStyleInterpolator

標頭各種組成部分的內插樣式。請參閱 動畫區段 以取得詳細資訊。

keyboardHandlingEnabled

如果為 false,在從此畫面導覽至新畫面的過程中,鍵盤將不會自動關閉。預設為 true

detachPreviousScreen

用於指出是否要從畫面層次中分離上一個畫面以節省記憶體的布林值。如果需要讓上一個畫面透過目前顯示的畫面看到,設定為 false。僅在未將 detachInactiveScreens 設定為 false 時適用。

使用 presentation 作為 transparentModalmodal 來保持必要的畫面可見時,會自動調整此設定。在其他情況下,預設為 true

freezeOnBlur

用於指出是否要避免重新渲染非作用中的畫面的布林值。預設為 false。當在應用程式的最上方執行 react-native-screens 套件的 enableFreeze() 時,預設為 true

需要 react-native-screens 版本 >=3.16.0。

僅在 iOS 和 Android 上受到支援。

您可以在 這裡 找到標題相關選項清單。這些 選項 可以指定在 Stack.navigatorscreenOptions 屬性或 Stack.Screenoptions 屬性下。您不需要直接使用 @react-navigation/elements 就能使用這些選項,它們只是記載在該頁面中。

除了這些之外,下列選項也受到堆疊支援

自訂標題,用於取代預設標題。

此選項接受一個函式,該函式會傳回一個 React 元素,來作為標題顯示。函式會收到一個物件,其中包含下列屬性,作為引數

  • navigation - 目前畫面的導覽物件。
  • route - 目前畫面的路徑物件。
  • options - 目前畫面的選項
  • layout - 畫面的尺寸,包含 heightwidth 屬性。
  • progress 動畫的進度所代表的動畫節點。
  • back - 返回按鈕的選項,包含一個物件,其中具有用於返回按鈕標籤的 title 屬性。
  • styleInterpolator - 傳回標題中各種元素的內插樣式的函式。

在使用自訂標題時,務必也將 headerMode 設定為 screen(有關更多資訊,請見下文)。

範例

import { getHeaderTitle } from '@react-navigation/elements';

// ..

header: ({ navigation, route, options, back }) => {
const title = getHeaderTitle(options, route.name);

return (
<MyHeader
title={title}
leftButton={
back ? <MyBackButton onPress={navigation.goBack} /> : undefined
}
style={options.headerStyle}
/>
);
};

若要為導覽器中的所有畫面設定一個自訂標題,您可以在導覽器的 screenOptions 屬性中指定此選項。

使用自訂標題時,有 2 件事要記住

headerStyle 中指定 height 以避免故障

如果標題高度與預設標題高度不同,由於測量是異步的,您可能會注意到故障。明確指定高度將會避免此類故障。

範例

headerStyle: {
height: 80, // Specify the height of your custom header
};

請注意,預設情況下標題並未套用此樣式,因為您可以控制自訂標題的造型。如果您還想將此樣式套用至標題,請使用屬性中的 headerStyle

headerMode 設定為 float 以取得自訂標題動畫

預設情況下,有一個浮動標題,可以為 iOS 中非模態視窗的多個畫面呈現標題。這些標題包含動畫,可以順利切換到另一個標題。

如果您指定自訂標題,React Navigation 會自動將其變更為 screen,以使標題與畫面一起進行動畫。這意味著您無須另外實作動畫來進行動畫處理。

但您可能想保留浮動標題,以在標題間有不同的轉場動畫。為執行這項操作,您需要在選項中指定 headerMode: 'float',然後在自訂標題中,靠 progress.currentprogress.next 屬性進行內插。例如,以下程式碼將交叉淡出標題

const opacity = Animated.add(progress.current, progress.next || 0).interpolate({
inputRange: [0, 1, 2],
outputRange: [0, 1, 0],
});

return (
<Animated.View style={{ opacity }}>{/* Header content */}</Animated.View>
);

headerMode

指定標題的呈現方式

  • float - 呈現一個單一標題,標題會停留在最上方,並在畫面變更時進行動畫。這是 iOS 的預設設定。
  • screen - 每個畫面都附有標題,且標題會隨著畫面淡入淡出。這是其他平台的預設設定。

headerShown

是否要為畫面顯示或隱藏標題。預設情況下會顯示標題。將此設定為 false 可隱藏標題。

headerBackAllowFontScaling

後退按鈕標題字型是否應調整以符合文字大小的輔助功能設定。預設為 false。

headerBackAccessibilityLabel

標題後退按鈕的輔助標籤。

headerBackImage

傳回 React 元件的函式,可在資訊列返回按鈕中顯示自訂的圖片。在使用函式時,它會於其引數物件中接收 tintColor。主功能是透過返回圖片來源來組成圖像元件,這是指定平台的預設返回圖示圖片(iOS 上的 V 形與 Android 上的箭頭)。

headerBackTitle

由 iOS 上的返回按鈕使用的標題字串。主功能是前一個場景的 headerTitle

headerBackTitleVisible

返回按鈕標題是否會顯示的合理解釋主功能已提供,但若您要覆寫主功能,可以於這個選項中使用 truefalse

headerTruncatedBackTitle

headerBackTitle 不符合螢幕大小時,由返回按鈕使用的標題字串。主功能是 "返回"

headerBackTitleStyle

返回標題的樣式物件。

事件

導覽器可在某些動作中傳送事件。所支援的事件為

transitionStart

此事件會在目前的螢幕開始轉場動畫時觸發。

事件資料

  • e.data.closing - 布林值,表示螢幕是否正在開啟或關閉。

範例

React.useEffect(() => {
const unsubscribe = navigation.addListener('transitionStart', (e) => {
// Do something
});

return unsubscribe;
}, [navigation]);

transitionEnd

此事件會在目前的螢幕結束轉場動畫時觸發。

事件資料

  • e.data.closing - 布林值,表示螢幕是否已開啟或關閉。

範例

React.useEffect(() => {
const unsubscribe = navigation.addListener('transitionEnd', (e) => {
// Do something
});

return unsubscribe;
}, [navigation]);

gestureStart

此事件會在目前的螢幕開始滑動手勢時觸發。

範例

React.useEffect(() => {
const unsubscribe = navigation.addListener('gestureStart', (e) => {
// Do something
});

return unsubscribe;
}, [navigation]);

gestureEnd

此事件會在目前的螢幕結束滑動手勢時觸發。例如,螢幕順利關閉。

範例

React.useEffect(() => {
const unsubscribe = navigation.addListener('gestureEnd', (e) => {
// Do something
});

return unsubscribe;
}, [navigation]);

gestureCancel

此事件會在目前的螢幕取消滑動手勢時觸發。例如,螢幕不會由手勢關閉。

範例

React.useEffect(() => {
const unsubscribe = navigation.addListener('gestureCancel', (e) => {
// Do something
});

return unsubscribe;
}, [navigation]);

輔助工具

堆疊導覽器會將下列的程式碼新增至導覽屬性

更換

以堆疊中的一個新畫面取代目前的畫面。此方法接受下列參數

  • 名稱 - 字串 - 推送到堆疊上的路徑名稱。
  • 參數 - 物件 - 要傳送到目標路徑的畫面參數。
navigation.replace('Profile', { owner: 'Michaś' });

推進

將一個新的畫面推送到堆疊頂端並導覽至該畫面。此方法接受下列參數

  • 名稱 - 字串 - 推送到堆疊上的路徑名稱。
  • 參數 - 物件 - 要傳送到目標路徑的畫面參數。
navigation.push('Profile', { owner: 'Michaś' });

彈出

從堆疊中彈出目前的畫面,並導覽回上一個畫面。它會接受一個可選參數 (計數),讓你指定要彈回幾個畫面。

navigation.pop();

彈出至頂端

彈出堆疊中除了第一個畫面以外的所有畫面,並導覽至第一個畫面。

navigation.popToTop();

範例

import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

function MyStack() {
return (
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerMode: 'screen',
headerTintColor: 'white',
headerStyle: { backgroundColor: 'tomato' },
}}
>
<Stack.Screen
name="Home"
component={Home}
options={{
title: 'Awesome app',
}}
/>
<Stack.Screen
name="Profile"
component={Profile}
options={{
title: 'My profile',
}}
/>
<Stack.Screen
name="Settings"
component={Settings}
options={{
gestureEnabled: false,
}}
/>
</Stack.Navigator>
);
}

動畫

堆疊導覽器公開各種選項來設定畫面加入或移除時的轉場動畫。這些轉場動畫可以透過在每個畫面的 選項 道具中指定選項來根據每個畫面進行自訂。

  • 手勢方向 - 滑動手勢的方向

    • 水平 - 關閉畫面的手勢會從左方開始,RTL 中則從右方開始。對於動畫,畫面會以 SlideFromRightIOS 從右方滑入,RTL 中則從左方滑入。
    • 水平反向 - 關閉畫面的手勢會從右方開始,RTL 中則從左方開始。對於動畫,畫面會以 SlideFromRightIOS 從左方滑入,RTL 中則從右方滑入,因為方向反向。
    • 垂直 - 關閉畫面的手勢會從上方開始。對於動畫,畫面會從下方滑入。
    • 垂直反向 - 關閉畫面的手勢會從下方開始。對於動畫,畫面會從上方滑入。

    你可能需要指定一個與 手勢方向 相符的水平/垂直動畫。對於函式庫中包含的動畫,如果你將 手勢方向 設為反向,它也會反轉動畫方向。

  • transitionSpec - 一個用於指定動畫類型(timingspring)及其選項(如 timingduration)的物件。它需要 2 個屬性

    • open - 新增畫面時過場效果的設定
    • close - 移除畫面時過場效果的設定。

    每個物件都應指定 2 個屬性

    • animation - 用於動畫的動畫函式。支援的值有 timingspring
    • config - 時序函式的設定物件。對於 timing,它可以是 durationeasing。對於 spring,它可以是 stiffnessdampingmassovershootClampingrestDisplacementThresholdrestSpeedThreshold

    使用彈簧動畫之設定範例如下

    const config = {
    animation: 'spring',
    config: {
    stiffness: 1000,
    damping: 500,
    mass: 3,
    overshootClamping: true,
    restDisplacementThreshold: 0.01,
    restSpeedThreshold: 0.01,
    },
    };

    我們可以在 transitionSpec 選項中傳遞此設定

    <Stack.Screen
    name="Profile"
    component={Profile}
    options={{
    transitionSpec: {
    open: config,
    close: config,
    },
    }}
    />
  • cardStyleInterpolator - 這是個用於為卡片不同部分指定插入式樣式的函式。這讓您可以自訂從一個畫面切換到另一個畫面的轉場效果。它至少應該回傳一個空物件,可能包含容器、卡片本身、疊加畫面和陰影的插入式樣式。支援的屬性包括

    • containerStyle - 包裹卡片的容器檢視樣式。
    • cardStyle - 表示卡片的檢視樣式。
    • overlayStyle - 表示下面半透明疊加畫面的檢視樣式
    • shadowStyle - 表示卡片陰影的檢視樣式。

    這個函式接收下列屬性作為引數

    • current - 目前畫面的值
      • progress - 目前畫面進度值的動畫節點。
    • next - 堆疊中下一個畫面的值。如果動畫畫面是最後一個畫面,這裡會是 undefined
      • progress - 下一個畫面的進度值的動畫節點。
    • index - 堆疊中卡片的索引。
    • closing - 動畫節點,用於表示卡片是否正在關閉。關閉時為 1,否則為 0
    • layouts - 我們可用於動畫的各個項目的配置測量。
      • screen - 整個畫面的配置。包含 heightwidth 屬性。

    請注意,當畫面不是最後一個時,將使用下一個畫面的過場效果設定。這是因為許多過場效果包含前一個畫面的動畫,因此這兩個過場效果需要一起使用,才能避免在兩個畫面上執行兩種不同的過場效果(例如滑動和模態)。您可以檢查 next 參數,找出是否要移除前一個畫面的動畫。有關此參數的更多資訊,請參閱 動畫 區段。

    使畫面淡出的設定範例如下

    const forFade = ({ current }) => ({
    cardStyle: {
    opacity: current.progress,
    },
    });

    我們可以在 cardStyleInterpolator 選項中傳遞此函式

    <Stack.Screen
    name="Profile"
    component={Profile}
    options={{ cardStyleInterpolator: forFade }}
    />

    интерполятор буде викликаний для кожного екрану. Наприклад, скажімо, що у вас є 2 екрани в стеку, A і B. B є новим екраном, що з'являється у фокусі, а А є попереднім екраном. Інтерполятор буде викликаний для кожного екрана

    • Інтерполятор викликається для B: Тут значення current.progress представляє прогрес переходу, який починається з 0 і закінчується на 1. Не буде next.progress, оскільки B є останнім екраном.
    • Інтерполятор викликається для A: Тут значення current.progress залишиться на рівні 1 і не зміниться, оскільки поточний перехід виконується для B, а не для A. Значення next.progress представляє прогрес B і почнеться з 0 і закінчиться на 1.

    Скажімо, ми хочемо анімувати обидва екрани під час переходу. Найпростіший спосіб зробити це - об’єднати значення прогресу поточних і наступних екранів

    const progress = Animated.add(
    current.progress.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 1],
    extrapolate: 'clamp',
    }),
    next
    ? next.progress.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 1],
    extrapolate: 'clamp',
    })
    : 0
    );

    Тут екран A матиме як current.progress, так і next.progress, і оскільки current.progress залишається на 1, а next.progress змінюється, разом узяті, прогрес зміниться з 1 на 2. Екран B матиме лише current.progress, який зміниться з 0 на 1. Таким чином, ми можемо застосовувати різні інтерполяції для 0-1 і 1-2, щоб анімувати відповідно сфокусований екран і нефокусований екран.

    Налаштування, яке трохи переміщує попередній екран ліворуч, а поточний - із правого краю, виглядатиме так

    const forSlide = ({ current, next, inverted, layouts: { screen } }) => {
    const progress = Animated.add(
    current.progress.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 1],
    extrapolate: 'clamp',
    }),
    next
    ? next.progress.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 1],
    extrapolate: 'clamp',
    })
    : 0
    );

    return {
    cardStyle: {
    transform: [
    {
    translateX: Animated.multiply(
    progress.interpolate({
    inputRange: [0, 1, 2],
    outputRange: [
    screen.width, // Focused, but offscreen in the beginning
    0, // Fully focused
    screen.width * -0.3, // Fully unfocused
    ],
    extrapolate: 'clamp',
    }),
    inverted
    ),
    },
    ],
    },
    };
    };
  • headerStyleInterpolator - це функція, яка визначає інтерпольовані стилі для різних частин заголовка. Очікується, що вона поверне принаймні порожній об’єкт, можливо, з інтерпольованими стилями для лівої мітки та кнопки, правої кнопки, заголовка та фону. Підтримувані властивості:

    • leftLabelStyle - Стиль для мітки лівої кнопки (мітка кнопки «Назад»).
    • leftButtonStyle - Стиль для лівої кнопки (зазвичай кнопки «Назад»).
    • rightButtonStyle - Стиль для правої кнопки.
    • titleStyle - Стиль для тексту заголовка.
    • backgroundStyle - Стиль для фону заголовка.

    Функція отримує такі властивості у своєму аргументі

    • current - Значення для поточного екрана (екран, якому належить цей заголовок).
      • progress - Анімований вузол, що представляє значення прогресу поточного екрана. 0, коли екран починає з'являтися, 0,5, коли він посередині, 1, коли він повинен бути повністю видимим.
    • next - 堆疊中下一個畫面的值。如果動畫畫面是最後一個畫面,這裡會是 undefined
      • progress - 下一個畫面的進度值的動畫節點。
    • layouts - Вимірювання макета для різних елементів, які ми використовуємо для анімації. Кожен об’єкт макета містить властивості height і width.
      • screen - Макет усього екрана.
      • title - Макет елемента заголовка. Може бути undefined, коли не відображається заголовок.
      • leftLabel - Макет мітки кнопки «Назад». Може бути undefined, коли не відображається мітка кнопки «Назад».

    Налаштування, яке просто затьмарює елементи, виглядає так

    const forFade = ({ current, next }) => {
    const opacity = Animated.add(
    current.progress,
    next ? next.progress : 0
    ).interpolate({
    inputRange: [0, 1, 2],
    outputRange: [0, 1, 0],
    });

    return {
    leftButtonStyle: { opacity },
    rightButtonStyle: { opacity },
    titleStyle: { opacity },
    backgroundStyle: { opacity },
    };
    };

    我們可以將此函數傳遞到headerStyleInterpolator選項

    <Stack.Screen
    name="Profile"
    component={Profile}
    options={{ headerStyleInterpolator: forFade }}
    />

預先製作好的設定檔

透過這些選項,我們就能夠為畫面製作自訂轉場動畫。我們也會從資料庫中匯出多種設定檔,其中包含您可以使用的現成動畫

TransitionSpecs

  • TransitionIOSSpec - 與UINavigationController動畫組態確切相同的值。
  • FadeInFromBottomAndroidSpec - Android Nougat開啟活動動畫的組態。
  • FadeOutToBottomAndroidSpec - Android Nougat關閉活動動畫的組態。
  • RevealFromBottomAndroidSpec - Android Pie開啟活動動畫的近似組態。

範例

import { TransitionSpecs } from '@react-navigation/stack';

// ...

<Stack.Screen
name="Profile"
component={Profile}
options={{
transitionSpec: {
open: TransitionSpecs.TransitionIOSSpec,
close: TransitionSpecs.TransitionIOSSpec,
},
}}
/>;

CardStyleInterpolators

  • forHorizontalIOS - 標準iOS樣式從右方滑動進入。
  • forVerticalIOS - 標準iOS樣式從底部滑動進入(用於模態視窗)。
  • forModalPresentationIOS - iOS 13的標準iOS樣式模態動畫。
  • forFadeFromBottomAndroid - Android Orero標準Android樣式從底部淡入。
  • forRevealFromBottomAndroid - Android Pie標準Android樣式從底部展開。

Android Oreo樣式垂直畫面淡化動畫的範例設定

import { CardStyleInterpolators } from '@react-navigation/stack';

// ...

<Stack.Screen
name="Profile"
component={Profile}
options={{
title: 'Profile',
cardStyleInterpolator: CardStyleInterpolators.forFadeFromBottomAndroid,
}}
/>;

HeaderStyleInterpolators

  • forUIKit - 標題淡入返回按鈕標籤的標準UIKit樣式動畫。
  • forFade - 標題元素的簡易淡化動畫。
  • forStatic - 簡易平移動畫,讓標題隨滑動畫面平移。

標題元素淡入返回按鈕的預設iOS動畫範例設定

import { HeaderStyleInterpolators } from '@react-navigation/stack';

// ...

<Stack.Screen
name="Profile"
component={Profile}
options={{
title: 'Profile',
headerStyleInterpolator: HeaderStyleInterpolators.forUIKit,
}}
/>;
警告

始終在檔案最頂層定義您的動畫組態,以確保在重新渲染時參照不會改變。這對於平順且穩定的轉場動畫來說非常重要。

TransitionPresets

我們匯出許多轉場預設值,它們會將這組選項中的各個選項組合起來,以符合特定的原生動畫。轉場預設值是一個物件,它包含在TransitionPresets底下匯出的幾個動畫相關畫面選項。目前有以下預設值

  • SlideFromRightIOS - 標準iOS導覽轉場。
  • ModalSlideFromBottomIOS - 標準iOS模態視窗導覽轉場。
  • ModalPresentationIOS - 標準iOS模態畫面呈現樣式(始於iOS 13)。
  • FadeFromBottomAndroid - Android < 9(Oreo)上開啟或關閉活動時的標準Android導覽轉場。
  • RevealFromBottomAndroid - Android 9(Pie)上開啟或關閉活動時的標準Android導覽轉場。
  • ScaleFromCenterAndroid - 開啟或在 Android >= 10 上關閉 Activity 時的標準 Android 導覽轉場動畫。
  • DefaultTransition - 目前平台的預設導覽轉場動畫。
  • ModalTransition - 目前平台的預設模式轉場動畫。

您可以在 options 中散布這些預設值,以自訂畫面的動態效果

import { TransitionPresets } from '@react-navigation/stack';

// ...

<Stack.Screen
name="Profile"
component={Profile}
options={{
title: 'Profile',
...TransitionPresets.ModalSlideFromBottomIOS,
}}
/>;

如果您想要自訂導覽器中所有畫面的轉場動態效果,您可以將它指定在導覽器的 screenOptions 屬性中。

適用於 iOS 模式簡報樣式的範例設定

import { TransitionPresets } from '@react-navigation/stack';

// ...

<Stack.Navigator
initialRouteName="Home"
screenOptions={({ route, navigation }) => ({
headerShown: false,
gestureEnabled: true,
...TransitionPresets.ModalPresentationIOS,
})}
>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Profile" component={Profile} />
</Stack.Navigator>;

透明模式

透明模式就像在畫面中疊加的模式對話方塊。先前的畫面仍舊保持在下方可見。如要取得透明模式畫面,您可以在畫面的選項中指定 presentation: 'transparentModal'

範例

<Stack.Navigator>
<Stack.Screen name="Home" component={HomeStack} />
<Stack.Screen
name="Modal"
component={ModalScreen}
options={{ presentation: 'transparentModal' }}
/>
</Stack.Navigator>

現在,當您導覽到 Modal 畫面時,它將會有一個透明背景,而 Home 畫面將在下方可見。

除了 presentation,您可能還想要選擇性地指定更多設定,以取得類似於模式對話方塊的行為

  • 使用 headerShown: false 停用標頭
  • 使用 cardOverlayEnabled: true 啟用覆蓋層(您無法透過點選覆蓋層來關閉畫面,請見下方的替代方案)

如果您想要進一步地自訂對話方塊的動態效果,或是希望在點選覆蓋層時關閉畫面,則可以使用 useCardAnimation 勾選方塊來自訂您畫面中的元素。

範例

import {
Animated,
View,
Text,
Pressable,
Button,
StyleSheet,
} from 'react-native';
import { useTheme } from '@react-navigation/native';
import { useCardAnimation } from '@react-navigation/stack';

function ModalScreen({ navigation }) {
const { colors } = useTheme();
const { current } = useCardAnimation();

return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Pressable
style={[
StyleSheet.absoluteFill,
{ backgroundColor: 'rgba(0, 0, 0, 0.5)' },
]}
onPress={navigation.goBack}
/>
<Animated.View
style={{
padding: 16,
width: '90%',
maxWidth: 400,
borderRadius: 3,
backgroundColor: colors.card,
transform: [
{
scale: current.progress.interpolate({
inputRange: [0, 1],
outputRange: [0.9, 1],
extrapolate: 'clamp',
}),
},
],
}}
>
<Text>
Mise en place is a French term that literally means “put in place. It
also refers to a way cooks in professional kitchens and restaurants
set up their work stations—first by gathering all ingredients for a
recipes, partially preparing them (like measuring out and chopping),
and setting them all near each other. Setting up mise en place before
cooking is another top tip for home cooks, as it seriously helps with
organization. It’ll pretty much guarantee you never forget to add an
ingredient and save you time from running back and forth from the
pantry ten times.
</Text>
<Button
title="Okay"
color={colors.primary}
style={{ alignSelf: 'flex-end' }}
onPress={navigation.goBack}
/>
</Animated.View>
</View>
);
}

在這裡我們將對話方塊的縮放進行動態效果,同時也加上一個覆蓋層來關閉對話方塊。