focusGroup 修飾子を使用すると、複数のフォーカス ターゲットをグループ化できます。グループ化を使用すると、フォーカス階層を管理し、論理 UI 領域(ツールバー、ダイアログ アクション、カードリストなど)を分離し、フォーカスが領域に出入りするときにインターセプトできます。
フォーカス グループのコンセプト: 入力、終了、デフォルトのトラバーサル
フォーカス グループは、子フォーカス ターゲットの周囲にまとまりのあるナビゲーション境界を確立します。この境界を越えてフォーカスが移動する仕組みを理解するには、次の 2 つの重要なコンセプトを理解する必要があります。
- Enter: フォーカス グループ外の要素からグループ内の要素にフォーカスが移動したときに発生するイベント。
- Exit: フォーカスがグループの最後の内部要素から離れ、外部のフォーカス ターゲットに移行したときに発生するイベント。
デフォルトのフォーカス走査動作
デフォルトでは、フォーカス グループが外部からフォーカスを受け取ると:
- グループへの入力: Compose は内部の子フォーカス ターゲットを自動的に選択します。1 次元(Tab)ナビゲーションの場合、視覚的な外観の順序で最初の子を選択します。2 次元(矢印キーまたは 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 などのスクロール可能なコンテナは、自動的にフォーカス グループとして機能します。onEnter または onExit コールバックを設定するために、focusGroup 修飾子を明示的に適用する必要はありません。
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- フォーカス ターゲット
- フォーカス移動順序
- テキスト フィールドのフォーカス
- フォーカスを復元する
- プログラムでフォーカスをリクエストする
- フォーカス ナビゲーションをテストする