焦点遍历顺序

用户可以使用 Tab 键或方向(箭头 / 方向键)键在界面元素之间移动键盘焦点:

  • Tab / Shift+Tab:按一维外观顺序向前或向后移动焦点。
  • 方向键:在二维空间内移动焦点(上、下、左和右)。

一维焦点遍历

在一维焦点遍历中,Tab 键会根据屏幕上的视觉显示顺序在界面中移动焦点。

例如,当四个按钮按行排列时:

Column {
    Row {
        Button(onClick = { /* ... */ }) { Text("1st") }
        Button(onClick = { /* ... */ }) { Text("2nd") }
    }
    Row {
        Button(onClick = { /* ... */ }) { Text("3rd") }
        Button(onClick = { /* ... */ }) { Text("4th") }
    }
}

按 Tab 键可按以下顺序在各个按钮之间依次移动焦点:

  1. 第 1 个按钮(顶部-开始)
  2. 第 2 个按钮(高端)
  3. 第 3 个按钮(底部开头)
  4. 第 4 个按钮(底部)

在最后一个元素上按 Tab 键会返回到第一个焦点目标。 按 Shift+Tab 可按相反的顺序移动焦点。

二维焦点遍历

按键盘箭头键或使用方向键会触发二维焦点遍历。

在二维遍历中,系统会检查界面元素的几何坐标和空间边界,以确定所请求方向上距离最近的目标。

二维焦点遍历不会循环。 如果用户在聚焦于最底部元素时按向下键,焦点会停留在该元素上,而不是跳到屏幕顶部。

通过指针点击重置焦点遍历

在桌面设备或大屏设备上,当在实体键盘与鼠标或触控板之间切换时:

  • 在点按或点击时清除焦点:使用鼠标或触控板点击非互动空间会释放活动元素的焦点。
  • 重新开始遍历:清除焦点后,下次按下 Tab 键时,系统会从视觉外观顺序中的第一个焦点目标重新开始一维遍历,而不是从之前获得焦点的元素继续遍历。 它与二维焦点遍历相同。方向键会将键盘焦点移动到所请求方向上最近的焦点目标。

如需详细了解如何以编程方式清除焦点,请参阅移动和清除焦点。

自定义焦点遍历顺序

您可以使用 focusProperties 修饰符自定义遍历行为。

自定义一维遍历顺序

如需替换一维遍历,请指定 next 或 previous 属性,并使用 FocusRequester:

  1. 使用 remember { FocusRequester() } 创建一个 FocusRequester 对象。
  2. 使用 focusRequester 修饰符将 FocusRequester 附加到目标可组合项。
  3. 将 focusProperties 修饰符应用于源可组合项,并将 FocusRequester 分配给 next(对于 Tab)或 previous(对于 Shift+Tab)。

val (first, second, third) = remember { FocusRequester.createRefs() }

Column {
    Button(
        onClick = { /* ... */ },
        modifier = Modifier
            .focusRequester(first)
            .focusProperties { next = third }
    ) {
        Text("First (Tab jumps to Third)")
    }
    Button(
        onClick = { /* ... */ },
        modifier = Modifier.focusRequester(second)
    ) {
        Text("Second")
    }
    Button(
        onClick = { /* ... */ },
        modifier = Modifier.focusRequester(third)
    ) {
        Text("Third")
    }
}

自定义二维遍历顺序

同样,您也可以通过在 focusProperties 内将 FocusRequester 实例分配给 up、down、start、end、left 或 right 来替换二维焦点遍历:

val (topButton, bottomButton) = remember { FocusRequester.createRefs() }

Button(
    onClick = { /* ... */ },
    modifier = Modifier
        .focusRequester(topButton)
        .focusProperties {
            down = bottomButton
            right = bottomButton
        }
) {
    Text("Top button")
}
Button(
    onClick = { /* ... */ },
    modifier = Modifier.focusRequester(bottomButton)
) {
    Text("Bottom button")
}

如需阻止特定方向(例如布局边界)的焦点导航,请将 FocusRequester.Cancel 分配给相应属性(例如 down = FocusRequester.Cancel)。如需明确保留系统针对给定方向的默认遍历算法,请分配 FocusRequester.Default。