フォーカス移動順序

ユーザーは Tab キーまたは方向(矢印 / D-pad)キーを使用して、UI 要素間でキーボード フォーカスを移動できます。

  • Tab / Shift+Tab: 1 次元の外観順序でフォーカスを前後に移動します。
  • 方向キー: フォーカスを 2 次元(上、下、左、右)に移動します。

1 次元のフォーカス走査

1 次元フォーカス走査では、画面上の視覚的な表示順序に基づいて、Tab キーで UI を通してフォーカスが移動します。

たとえば、4 つのボタンが横一列に配置されている場合:

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 キーを押すと、フォーカスが逆順に移動します。

2 次元フォーカス走査

キーボードの矢印キーを押すか、D-pad を使用すると、2 次元のフォーカス走査がトリガーされます。

2 次元の走査では、システムは UI 要素の幾何学的座標と空間境界を検査し、リクエストされた方向で最も近いターゲットを特定します。

2 次元フォーカス走査はラップアラウンドしません。ユーザーが最下部の要素にフォーカスを当てた状態で下キーを押すと、フォーカスは画面の上部に移動するのではなく、その要素に残ります。

ポインタのクリックでフォーカス移動をリセット

デスクトップ デバイスまたは大画面デバイスで物理キーボードとマウスまたはタッチパッドを切り替える場合:

  • タップまたはクリックでフォーカスをクリア: マウスまたはタッチパッドで操作できないスペースをクリックまたはタップすると、アクティブな要素からフォーカスが解除されます。
  • 走査を再開する: フォーカスがクリアされた後、次の Tab キーを押すと、以前アクティブだった要素から再開するのではなく、視覚的な順序で最初のフォーカス ターゲットから 1 次元走査が再開されます。2 次元フォーカス走査と同じです。方向キーは、リクエストされた方向で最も近いフォーカス ターゲットにキーボード フォーカスを移動します。

プログラムでフォーカスをクリアする方法について詳しくは、フォーカスを移動してクリアするをご覧ください。

フォーカス移動順序をカスタマイズする

トラバーサルの動作は、focusProperties 修飾子でカスタマイズできます。

1 次元トラバーサル順序をカスタマイズする

1 次元トラバーサルをオーバーライドするには、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")
    }
}

2 次元移動順序をカスタマイズする

同様に、focusProperties 内の up、down、start、end、left、right に FocusRequester インスタンスを割り当てることで、2 次元フォーカス トラバーサルをオーバーライドできます。

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")
}

特定の方向(レイアウトの境界など)のフォーカス ナビゲーションをブロックするには、そのプロパティ(down = FocusRequester.Cancel など)に FocusRequester.Cancel を割り当てます。特定の方向でシステムのデフォルトのトラバーサル アルゴリズムを明示的に保持するには、FocusRequester.Default を割り当てます。