導覽是指使用者在應用程式中移動的方式。使用者通常會輕觸或點選 UI 元素進行互動,應用程式則會回應並顯示新內容。如果使用者想返回先前的內容,可以使用返回手勢或輕觸返回按鈕。
模擬導覽狀態
使用內容堆疊是模擬這類行為的方便方法。當使用者向前瀏覽新內容時,系統會將該內容推送至堆疊頂端。當使用者從該內容「返回」時,系統會將該內容彈出堆疊,並顯示先前的內容。在導覽用語中,這個堆疊通常稱為「返回堆疊」,因為它代表使用者「可以返回」的內容。

建立返回堆疊
在 Navigation 3 中,返回堆疊實際上不含任何內容。而是包含內容參照,也就是所謂的鍵。鍵可以是任何類型,但通常是簡單的序列化資料類別。使用參照而非內容有以下優點:
- 只要將按鍵推送至返回堆疊,即可輕鬆瀏覽。
- 只要鍵可序列化,返回堆疊就能儲存至永久性儲存空間,讓返回堆疊在設定變更和程序終止後繼續留存。這一點很重要,因為使用者預期可以離開應用程式,稍後再回來,並在相同的內容顯示畫面中繼續瀏覽。詳情請參閱「儲存返回堆疊」一文。
Navigation 3 API 中的重要概念是您擁有後置堆疊。程式庫:
- 預期返回堆疊會是快照狀態備份的
List<T>
,其中T
是返回堆疊keys
的類型。您可以使用Any
,也可以提供更強型別的鍵。當您看到「push」或「pop」時,底層實作方式是在清單結尾處新增或移除項目。 - 觀察返回堆疊,並使用
NavDisplay
在 UI 中反映其狀態。
以下範例說明如何建立鍵和返回堆疊,並修改返回堆疊以回應使用者導覽事件:
// Define keys that will identify content data object ProductList data class ProductDetail(val id: String) @Composable fun MyApp() { // Create a back stack, specifying the key the app should start with val backStack = remember { mutableStateListOf<Any>(ProductList) } // Supply your back stack to a NavDisplay so it can reflect changes in the UI // ...more on this below... // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state backStack.add(ProductDetail(id = "ABC")) // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state backStack.removeLastOrNull() }
將鍵解析為內容
在 Navigation 3 中,使用 NavEntry
模擬內容,這是包含可組合函式的類別。代表目的地:使用者可以前往和返回的單一內容。
NavEntry
也可能包含中繼資料,也就是內容相關資訊。容器物件 (例如 NavDisplay
) 可以讀取這類中繼資料,藉此決定如何顯示 NavEntry
的內容。舉例來說,您可以使用中繼資料覆寫特定 NavEntry
的預設動畫。NavEntry metadata
是 String
鍵與 Any
值的對應,可提供多樣化的資料儲存空間。
如要將 key
轉換為 NavEntry
,請建立 entryProvider
。這個函式會接受 key
,並傳回該 key
的 NavEntry
。在建立 NavDisplay
時,通常會將其定義為 lambda 參數。
建立 entryProvider
的方式有兩種,您可以直接建立 lambda 函式,也可以使用 entryProvider
DSL。
直接建立 entryProvider
函式
您通常會使用 when
陳述式建立 entryProvider
函式,並為每個鍵建立分支。
entryProvider = { key -> when (key) { is ProductList -> NavEntry(key) { Text("Product List") } is ProductDetail -> NavEntry( key, metadata = mapOf("extraDataKey" to "extraDataValue") ) { Text("Product ${key.id} ") } else -> { NavEntry(Unit) { Text(text = "Invalid Key: $it") } } } }
使用 entryProvider
DSL
entryProvider
DSL 可避免您需要針對每個鍵類型進行測試,並為每個鍵類型建構 NavEntry
,藉此簡化 lambda 函式。請使用 entryProvider
建構函式。如果找不到索引鍵,也會包含預設的備用行為 (擲回錯誤)。
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
請注意程式碼片段中的以下事項:
entry
可用於定義具有指定類型和可組合內容的NavEntry
entry
會接受metadata
參數,用於設定NavEntry.metadata
顯示返回堆疊
返回堆疊代表應用程式的導覽狀態。只要返回堆疊發生變更,應用程式 UI 就應反映新的返回堆疊狀態。在 Navigation 3 中,NavDisplay
會觀察返回堆疊,並據此更新 UI。請使用下列參數建構:
- 返回堆疊 - 應為
SnapshotStateList<T>
類型,其中T
是返回堆疊鍵的類型。這是可觀察的List
,因此會在變更時觸發NavDisplay
的重組作業。 entryProvider
,用於將返回堆疊中的鍵轉換為NavEntry
。- 您可以選擇為
onBack
參數提供 lambda。當使用者觸發返回事件時,系統會呼叫此方法。
以下範例說明如何建立 NavDisplay
。
data object Home data class Product(val id: String) @Composable fun NavExample() { val backStack = remember { mutableStateListOf<Any>(Home) } NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = { key -> when (key) { is Home -> NavEntry(key) { ContentGreen("Welcome to Nav3") { Button(onClick = { backStack.add(Product("123")) }) { Text("Click to navigate") } } } is Product -> NavEntry(key) { ContentBlue("Product ${key.id} ") } else -> NavEntry(Unit) { Text("Unknown route") } } } ) }
根據預設,NavDisplay
會在單一窗格版面配置中顯示後置堆疊上最頂層的 NavEntry
。以下錄影畫面顯示此應用程式執行情形:

NavDisplay
具有兩個目的地的預設行為。平台比一比
下圖顯示 Navigation 3 中各個物件之間的資料流動方式:

導覽事件會啟動變更。系統會根據使用者互動內容,在返回堆疊中新增或移除鍵。
返回堆疊狀態變更會觸發內容擷取作業。
NavDisplay
(用於轉譯返回堆疊的可組合函式) 會觀察返回堆疊。在預設設定中,它會在單一窗格版面配置中顯示最頂層的返回堆疊項目。當返回堆疊的頂端鍵變更時,NavDisplay
會使用這個鍵向輸入供應器要求對應的內容。供應者提供內容。項目提供者是將索引鍵解析為
NavEntry
的函式。接收NavDisplay
提供的金鑰後,輸入提供者會提供相關聯的NavEntry
,其中包含金鑰和內容。顯示內容。
NavDisplay
會接收NavEntry
並顯示內容。