使用者透過硬體鍵盤或 D-Pad 瀏覽複雜的使用者介面時,經常會在螢幕的不同區段之間移動,例如從側邊導覽列跳到內容清單、與項目互動,然後跳回。焦點還原功能可讓容器記住先前焦點所在的子項元素,並在焦點重新進入容器時還原至該元素。
在可捲動的容器中還原焦點
在 Jetpack Compose 中,LazyColumn、LazyRow 和 LazyVerticalGrid 等可捲動的容器會自動做為焦點群組。如要在延遲載入的清單或格線中啟用焦點還原功能,請附加 focusRestorer 修飾符:
LazyColumn( modifier = Modifier.focusRestorer() ) { items(items) { item -> Button(onClick = { /* Handle click */ }) { Text(item) } } }
焦點離開 LazyColumn 時,容器會記錄哪個項目處於啟用狀態。
當使用者返回清單時,焦點會還原至該項目,而不是從頂端重新開始。
還原列和欄中的焦點
與延遲版面配置容器不同,標準非捲動式版面配置容器 (例如 Row 和 Column) 預設不會建立焦點邊界。因為這些修飾符本身不會攔截焦點輸入事件,因此單獨套用 focusRestorer 修飾符是不夠的。
如要在 Row 或 Column 上啟用焦點還原功能,請將 focusGroup 與 focusRestorer 結合:
Row( modifier = Modifier .focusGroup() .focusRestorer() ) { Button(onClick = { /* Action 1 */ }) { Text("First item") } Button(onClick = { /* Action 2 */ }) { Text("Second item") } Button(onClick = { /* Action 3 */ }) { Text("Third item") } }
指定備用焦點目標
焦點首次進入容器時, 沒有先前焦點子項。 Compose 會依預設焦點順序決定要將焦點放在哪個子項。
您可以傳遞後備 FocusRequester 至 focusRestorer (或在較早的 Compose 版本中傳遞傳回 FocusRequester 的 lambda),自訂首次輸入時要將焦點移至哪個子項:
val firstItemRequester = remember { FocusRequester() } LazyColumn( modifier = Modifier.focusRestorer(firstItemRequester) ) { itemsIndexed(items) { index, item -> val itemModifier = if (index == 0) { Modifier.focusRequester(firstItemRequester) } else { Modifier } Button( onClick = { /* Handle click */ }, modifier = itemModifier ) { Text(item) } } }
如果先前沒有聚焦任何子項 (或焦點還原失敗),Compose 會將焦點移至相關聯的回退目標。
將焦點直接放在導覽元件中的所選項目
在 NavigationRail、NavigationBar、NavigationDrawer 或 TabRow 等導覽元件中,使用者從內容區域進入元件時,預期焦點會落在目前選取的目的地。
您可以結合 Modifier.focusGroup() 和 focusProperties,並設定 onEnter 屬性 (或舊版 Compose 的 enter),將焦點導向有效目的地:
val (homeRequester, searchRequester, settingsRequester) = remember { FocusRequester.createRefs() } val selectedRequester = when (currentDestination) { "home" -> homeRequester "search" -> searchRequester "settings" -> settingsRequester else -> homeRequester } NavigationRail( modifier = modifier .focusProperties { // Redirect focus to the selected item when focus enters the navigation rail onEnter = { selectedRequester.requestFocus() } } .focusGroup() ) { NavigationRailItem( selected = currentDestination == "home", onClick = { onNavigate("home") }, icon = { Icon(Icons.Default.Home, contentDescription = "Home") }, label = { Text("Home") }, modifier = Modifier.focusRequester(homeRequester) ) NavigationRailItem( selected = currentDestination == "search", onClick = { onNavigate("search") }, icon = { Icon(Icons.Default.Search, contentDescription = "Search") }, label = { Text("Search") }, modifier = Modifier.focusRequester(searchRequester) ) NavigationRailItem( selected = currentDestination == "settings", onClick = { onNavigate("settings") }, icon = { Icon(Icons.Default.Settings, contentDescription = "Settings") }, label = { Text("Settings") }, modifier = Modifier.focusRequester(settingsRequester) ) }
在畫面轉換期間還原焦點
使用者點選項目前往詳細資料畫面,然後使用返回按鈕或手勢返回時,您可以將焦點還原至使用者點選的項目。
如要在畫面轉換時保留及還原焦點,請按照下列步驟操作:
- 將容器與
FocusRequester建立關聯。 - 觸發導覽事件前,請在容器的
FocusRequester上呼叫saveFocusedChild()。 - 使用者返回畫面時,請要求將初始焦點放在容器上,或呼叫
restoreFocusedChild()。