您可以使用 focusGroup 修飾符,將多個焦點目標分組。分組功能可讓您管理焦點階層、隔離邏輯 UI 區域 (例如工具列、對話方塊動作或資訊卡清單),以及在焦點進入或離開區域時進行攔截。
焦點團體概念:進入、退出及預設遍歷
焦點群組會在子項焦點目標周圍建立連貫的瀏覽邊界。如要瞭解焦點如何跨越這個界線移動,需要掌握兩個重要概念:
- 進入:當焦點從焦點群組外的任何元素,轉移至群組內的元素時,就會觸發這個事件。
- 離開:當焦點離開群組的最後一個內部元素,並轉換為外部焦點目標時,就會發生這個事件。
預設焦點遍歷行為
根據預設,當焦點群組從外部接收焦點時:
- 進入群組:Compose 會自動選取內部子項焦點目標。如果是單一維度 (Tab) 導覽,系統會依視覺外觀順序選取第一個子項。如果是二維 (箭頭鍵或 D-Pad) 導覽,系統會選取幾何上最接近輸入方向的子項。
- 在群組內導覽:重複按下導覽鍵,即可在群組封閉的同層級焦點目標之間移動焦點。
- 離開群組:使用者瀏覽過群組內最後一個焦點目標後,下次按下按鍵時就會離開群組,並將焦點移至群組外相鄰的焦點目標。
自訂焦點項目重新導向
在許多 UI 設計中,預設的進入目標 (例如外觀順序中的第一個子項) 並非最符合邏輯或最方便使用者的選擇。
意圖和用途
請考慮使用確認對話方塊,左側為「取消」按鈕,右側為主要「確認」按鈕。使用者從表單欄位向下瀏覽至按鈕列時:
- 預設行為:焦點會落在「取消」上,因為這是視覺外觀順序中的第一個按鈕。
- 預期行為:「確認」是主要建議動作,因此當您從焦點順序較早的位置進入按鈕群組時,焦點可能會直接落在「確認」上,但使用者仍可視需要按下「向左」選取「取消」。
其他常見用途包括:
- 在輸入
TabRow時,直接將焦點移至目前所選分頁。 - 進入媒體播放列時,直接將焦點移至「播放 / 暫停」控制項。
使用 onEnter 和 FocusRequester 實作
如要在進入焦點團體時重新導向焦點,請按照下列步驟操作:
- 將
focusGroup修飾符套用至封閉相關焦點目標的上層容器。 - 將
focusProperties修飾符套用至容器,並設定onEnter回呼。 - 在
onEnter回呼 (範圍為FocusEnterExitScope) 中,使用focusRequester,在與偏好的預設子項相關聯的FocusRequester上呼叫requestFocus()。
val defaultChildRequester = remember { FocusRequester() } Row( modifier = Modifier .focusGroup() .focusProperties { // Intercept entry into this group and redirect focus to the primary action onEnter = { defaultChildRequester.requestFocus() } } ) { Button(onClick = { /* Cancel action */ }) { Text("Cancel") } Button( onClick = { /* Confirm action */ }, modifier = Modifier.focusRequester(defaultChildRequester) ) { Text("Confirm (Default)") } }
在 onEnter 和 onExit 內,您也可以呼叫 cancelFocusChange(),完全封鎖邊界間的焦點轉移,或檢查 requestedFocusDirection,根據使用者是否使用 Tab、Down 或 Left 鍵導覽,自訂路徑。
可捲動容器預設為焦點群組
在 Jetpack Compose 中,LazyRow、LazyColumn 和 LazyVerticalGrid 等可捲動的容器會自動做為焦點群組。您不需要明確將 focusGroup 修飾符套用至這些項目,即可設定 onEnter 或 onExit 回呼。