Compose アプリのユーザー補助スクリーン リーダーの動作はデフォルトで実装されている
通常は左から右、上から下の順になります。
ただし、アルゴリズムが決定できないタイプのアプリ レイアウトもあります。
ヒントなしで実際の読む順番が示されています。ビューベースのアプリでは、次の操作が可能です。
traversalBefore
プロパティと traversalAfter
プロパティを使用して、このような問題を修正します。
Compose 1.5 以降、Compose は同等の柔軟な API を提供しますが、
説明します。
isTraversalGroup
と traversalIndex
はセマンティック プロパティです。
を使用すると、
デフォルトの並べ替えアルゴリズムは適切ではありません。isTraversalGroup
の識別情報
意味的に重要なグループですが、traversalIndex
は順序を調整します。
グループ化しますisTraversalGroup
は単独でも使用できますが、
または traversalIndex
を使用すると、さらにカスタマイズできます。
isTraversalGroup
と traversalIndex
を
アプリでスクリーン リーダーの移動順序を制御します。
isTraversalGroup
で要素をグループ化する
isTraversalGroup
はブール値のプロパティであり、セマンティクス
トラバーサルグループですこのタイプのノードは、リソースを提供するという
ノードの子を編成する際の境界または境界として使用します。
ノードに isTraversalGroup = true
を設定すると、そのノードのすべての子が
移動してから他の要素に移動できますisTraversalGroup
を ON に設定できます
スクリーン リーダー以外のフォーカス可能なノード(列、行、ボックスなど)。
次の例では、isTraversalGroup
を使用しています。4 つのテキスト要素を出力します。「
左の 2 つの要素は 1 つの CardBox
要素に属し、右の 2 つの要素は
次のように別の CardBox
要素に属します。
// CardBox() function takes in top and bottom sample text.
@Composable
fun CardBox(
topSampleText: String,
bottomSampleText: String,
modifier: Modifier = Modifier
) {
Box(modifier) {
Column {
Text(topSampleText)
Text(bottomSampleText)
}
}
}
@Composable
fun TraversalGroupDemo() {
val topSampleText1 = "This sentence is in "
val bottomSampleText1 = "the left column."
val topSampleText2 = "This sentence is "
val bottomSampleText2 = "on the right."
Row {
CardBox(
topSampleText1,
bottomSampleText1
)
CardBox(
topSampleText2,
bottomSampleText2
)
}
}
このコードにより、次のような出力が生成されます。

セマンティクスが設定されていないため、スクリーン リーダーのデフォルトの動作は次のとおりです。 要素を左から右、上から下にトラバースできます。このため、 デフォルトでは、TalkBack は文の断片を間違った順序で読み上げます。
「この文が含まれています」→ 「この文は」→ 「左の列」を選択します。→ " あります
フラグメントを正しく並べ替えるには、元のスニペットを変更して
isTraversalGroup
から true
:
@Composable
fun TraversalGroupDemo2() {
val topSampleText1 = "This sentence is in "
val bottomSampleText1 = "the left column."
val topSampleText2 = "This sentence is"
val bottomSampleText2 = "on the right."
Row {
CardBox(
// 1,
topSampleText1,
bottomSampleText1,
Modifier.semantics { isTraversalGroup = true }
)
CardBox(
// 2,
topSampleText2,
bottomSampleText2,
Modifier.semantics { isTraversalGroup = true }
)
}
}
isTraversalGroup
は CardBox
ごとに特別に設定されるため、CardBox
境界は要素を並べ替える際に適用されます。この例では
最初に CardBox
が読み込まれ、次に右側の CardBox
が読み取られます。
これで、TalkBack が正しい順序で文の断片を読み上げるようになりました。
「この文が含まれています」→ 「左の列」を選択します。→ 「この文は」→ " あります
移動順序をさらにカスタマイズする
traversalIndex
は、TalkBack をカスタマイズできる浮動小数点プロパティです。
移動順序を指定します要素をグループ化するだけでは TalkBack が
traversalIndex
を以下と組み合わせて使用すると、
スクリーン リーダーの順序をさらにカスタマイズするには、isTraversalGroup
を使用します。
traversalIndex
プロパティには次の特徴があります。
traversalIndex
の値が小さい要素が優先されます。- 正数または負数を指定できます。
- デフォルト値は
0f
です。 - 画面上の要素など、スクリーン リーダーのフォーカス可能なノードにのみ影響します。
できます。たとえば、1 つの列に
traversalIndex
のみを設定すると、 列にisTraversalGroup
も設定されていない限り、効果はありません。
次の例は、traversalIndex
と
一緒に isTraversalGroup
しましょう。
例: 時計の文字盤をトラバースする
時計の文字盤は、標準的なトラバーサルの順序付けが行われない一般的なシナリオです。 説明します。このセクションの例は時間選択ツールです。ユーザーはこの時間選択ツールを使用して、 文字盤の数字を通し、時間と分の数字を選択します あります。

次の簡略化されたスニペットでは、CircularLayout
で、12 個を
12 から始めて、円の周りに時計回りに数字が描画されます。
@Composable
fun ClockFaceDemo() {
CircularLayout {
repeat(12) { hour ->
ClockText(hour)
}
}
}
@Composable
private fun ClockText(value: Int) {
Box(modifier = Modifier) {
Text((if (value == 0) 12 else value).toString())
}
}
時計の文字盤は、デフォルトの左から右に論理的に読み取られていないため、 上から下に並べられている場合、TalkBack は数字を順番に読み上げます。修正方法 次のスニペットに示すように、インクリメントするカウンタ値を使用します。
@Composable
fun ClockFaceDemo() {
CircularLayout(Modifier.semantics { isTraversalGroup = true }) {
repeat(12) { hour ->
ClockText(hour)
}
}
}
@Composable
private fun ClockText(value: Int) {
Box(modifier = Modifier.semantics { this.traversalIndex = value.toFloat() }) {
Text((if (value == 0) 12 else value).toString())
}
}
移動の順序を適切に設定するには、まず CircularLayout
を
トラバーサルグループを作成し、isTraversalGroup = true
を設定します。時計の文字が
対応する traversalIndex
をカウンタに設定します。
あります。
カウンタ値は継続的に増加するため、各クロック値は
traversalIndex
は、画面に数値が追加されると大きくなります(時計値は 0)。
traversalIndex
は 0 で、クロック値 1 は traversalIndex
1 です。
これにより、TalkBack が読み上げる順序が設定されます。この数値は
CircularLayout
内のデータは期待される順序で読み取られます。
設定された traversalIndexes
は他の相対値のみであるため、
同じグループ内に複数のインデックスがある場合、
保持されます。言い換えると、上のコードに示したセマンティックな変化は、
スニペットは、文字盤内の順序を変更します。
isTraversalGroup = true
が設定されました。
なお、CircularLayout's
セマンティクスを isTraversalGroup =
true
に設定しなくても、traversalIndex
の変更が適用されます。ただし、
CircularLayout
でバインドすると、文字盤の 12 桁の数字が読み取られます。
最後の要素です。この問題は、
他のすべての要素にはデフォルトの traversalIndex
が 0f
であり、
時計のテキスト要素は、他のすべての 0f
要素の後で読み取られます。
例: フローティング アクション ボタンの移動順序をカスタマイズする
この例では、traversalIndex
と isTraversalGroup
が
マテリアル デザインのフローティング アクション ボタン(FAB)の移動順序。基礎
次のレイアウトを見てみましょう。

このサンプルのレイアウトでは、デフォルトで TalkBack は次のようになります。
トップ アプリバー → サンプル テキスト 0 ~ 6 → フローティング アクション ボタン(FAB)→ 下部 アプリバー
スクリーン リーダーでは、まず FAB にフォーカスを合わせることをおすすめします。目標の値を設定するには、
FAB などのマテリアル要素で traversalIndex
を設定するには、次のようにします。
@Composable
fun FloatingBox() {
Box(modifier = Modifier.semantics { isTraversalGroup = true; traversalIndex = -1f }) {
FloatingActionButton(onClick = {}) {
Icon(imageVector = Icons.Default.Add, contentDescription = "fab icon")
}
}
}
このスニペットでは、スペースを作成し、
同じボックスで isTraversalGroup
を true
に設定し、traversalIndex
を設定している
(-1f
がデフォルト値の 0f
よりも小さい)は、フローティング ボックスが
画面上の他のすべての要素よりも前に配置されます。
次に、フローティング ボックスやその他の要素をスキャフォールドに配置します。 マテリアル デザイン レイアウトを実装します。
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ColumnWithFABFirstDemo() {
Scaffold(
topBar = { TopAppBar(title = { Text("Top App Bar") }) },
floatingActionButtonPosition = FabPosition.End,
floatingActionButton = { FloatingBox() },
content = { padding -> ContentColumn(padding = padding) },
bottomBar = { BottomAppBar { Text("Bottom App Bar") } }
)
}
TalkBack は、次の順序で要素を操作できます。
FAB → トップ アプリバー → サンプル テキスト 0 ~ 6 → ボトム アプリバー
参考情報
- ユーザー補助: 基本的なコンセプトと すべての Android アプリ開発に共通する手法
- 利用しやすいアプリを作成する: 主な手順 アプリのユーザー補助機能を強化する方法を
- アプリを改善する原則 アクセシビリティ: アプリのユーザー補助機能を強化する方法を
- ユーザー補助機能のテスト: Android のユーザー補助機能のテスト原則とツール