アクセシビリティ
AndroidとiOSはどちらも、VoiceOver(iOS)やTalkBack(Android)などのバンドルされたスクリーンリーダーをはじめとする支援技術とアプリを統合するためのAPIを提供しています。React Nativeには、すべてのユーザーに対応できる補完的なAPIがあります。
AndroidとiOSではアプローチが若干異なり、そのためReact Nativeの実装はプラットフォームによって異なる場合があります。
アクセシビリティプロパティ
accessible
true
の場合、ビューがアクセシビリティ要素であることを示します。ビューがアクセシビリティ要素の場合、その子要素を1つの選択可能なコンポーネントにグループ化します。デフォルトでは、すべてのタッチ可能な要素はアクセス可能です。
Androidでは、react-native Viewの`accessible={true}`プロパティは、ネイティブの`focusable={true}`に変換されます。
<View accessible={true}>
<Text>text one</Text>
<Text>text two</Text>
</View>
上記の例では、アクセシビリティフォーカスは`accessible`プロパティを持つ親ビューでのみ使用可能であり、「テキスト1」と「テキスト2」で個別に使用することはできません。
accessibilityLabel
ビューがアクセス可能としてマークされている場合、VoiceOverまたはTalkBackを使用しているユーザーがどの要素を選択したかを知ることができるように、ビューに`accessibilityLabel`を設定することをお勧めします。スクリーンリーダーは、関連付けられた要素が選択されたときに、この文字列を読み上げます。
使用するには、View、Text、またはTouchableの`accessibilityLabel`プロパティをカスタム文字列に設定します。
<TouchableOpacity
accessible={true}
accessibilityLabel="Tap me!"
onPress={onPress}>
<View style={styles.button}>
<Text style={styles.buttonText}>Press me!</Text>
</View>
</TouchableOpacity>
上記の例では、TouchableOpacity要素の`accessibilityLabel`はデフォルトで「Press me!」になります。ラベルは、すべてのTextノードの子をスペースで区切って連結することによって構築されます。
accessibilityLabelledBy
Android
複雑なフォームを構築するために使用される別の要素nativeIDへの参照です。 `accessibilityLabelledBy`の値は、関連する要素の`nativeID`と一致する必要があります。
<View>
<Text nativeID="formLabel">Label for Input Field</Text>
<TextInput
accessibilityLabel="input"
accessibilityLabelledBy="formLabel"
/>
</View>
上記の例では、TextInputにフォーカスを合わせると、スクリーンリーダーは「入力、入力フィールドのラベルの編集ボックス」と読み上げます。
accessibilityHint
アクセシビリティヒントは、アクセシビリティラベルだけでは明確でない場合に、アクションの結果についてユーザーに追加のコンテキストを提供するために使用できます。
View、Text、またはTouchableの`accessibilityHint`プロパティにカスタム文字列を指定します。
<TouchableOpacity
accessible={true}
accessibilityLabel="Go back"
accessibilityHint="Navigates to the previous screen"
onPress={onPress}>
<View style={styles.button}>
<Text style={styles.buttonText}>Back</Text>
</View>
</TouchableOpacity>
上記の例では、ユーザーがデバイスのVoiceOver設定でヒントを有効にしている場合、VoiceOverはラベルの後にヒントを読み上げます。 `accessibilityHint`のガイドラインの詳細については、iOSデベロッパードキュメントをご覧ください。
上記の例では、TalkBackはラベルの後にヒントを読み上げます。現時点では、Androidではヒントをオフにすることはできません。
accessibilityLanguage
iOS
`accessibilityLanguage`プロパティを使用することで、スクリーンリーダーは要素の**ラベル**、**値**、**ヒント**を読み上げる際に使用する言語を理解します。指定する文字列値は、BCP 47仕様に従う必要があります。
<View
accessible={true}
accessibilityLabel="Pizza"
accessibilityLanguage="it-IT">
<Text>🍕</Text>
</View>
accessibilityIgnoresInvertColors
iOS
画面の色を反転する機能は、iOSとiPadOSで利用できる、色覚異常、弱視、視覚障碍のある方向けのアクセシビリティ機能です。この設定がオンのときに反転したくないビュー(おそらく写真)がある場合は、このプロパティを`true`に設定します。
accessibilityLiveRegion
Android
コンポーネントが動的に変更された場合、TalkBackでエンドユーザーに警告したい場合があります。これは、`accessibilityLiveRegion`プロパティによって実現できます。 `none`、`polite`、`assertive`に設定できます。
- **none** アクセシビリティサービスはこのビューへの変更を読み上げません。
- **polite** アクセシビリティサービスはこのビューへの変更を読み上げます。
- **assertive** アクセシビリティサービスは、現在読み上げている内容を中断して、このビューへの変更をすぐに読み上げます。
<TouchableWithoutFeedback onPress={addOne}>
<View style={styles.embedded}>
<Text>Click me</Text>
</View>
</TouchableWithoutFeedback>
<Text accessibilityLiveRegion="polite">
Clicked {count} times
</Text>
上記の`addOne`メソッドの例では、状態変数`count`が変更されます。 TouchableWithoutFeedbackがトリガーされると、`accessibilityLiveRegion="polite"`プロパティが設定されているため、TalkBackはTextビュー内のテキストを読み上げます。
accessibilityRole
accessibilityRole
は、コンポーネントの目的を支援技術のユーザーに伝えます。
accessibilityRole
は以下のいずれかになります。
- **adjustable** 要素が「調整可能」(例:スライダー)な場合に使用します。
- **alert** 要素にユーザーに提示する重要なテキストが含まれている場合に使用します。
- **button** 要素をボタンとして扱う必要がある場合に使用します。
- **checkbox** 要素が、オン、オフ、または中間状態を持つチェックボックスを表す場合に使用します。
- **combobox** 要素がコンボボックスを表す場合に使用します。コンボボックスでは、ユーザーは複数の選択肢から選択できます。
- **header** 要素がコンテンツセクションのヘッダーとして機能する場合(例:ナビゲーションバーのタイトル)に使用します。
- **image** 要素を画像として扱う必要がある場合に使用します。ボタンまたはリンクと組み合わせることができます。
- **imagebutton** 要素をボタンとして扱う必要があり、かつ画像でもある場合に使用します。
- **keyboardkey** 要素がキーボードキーとして機能する場合に使用します。
- **link** 要素をリンクとして扱う必要がある場合に使用します。
- **menu** コンポーネントが選択肢のメニューである場合に使用します。
- **menubar** コンポーネントが複数のメニューのコンテナである場合に使用します。
- **menuitem** メニュー内の項目を表すために使用します。
- **none** 要素にロールがない場合に使用します。
- **progressbar** タスクの進捗状況を示すコンポーネントを表すために使用します。
- **radio** ラジオボタンを表すために使用します。
- **radiogroup** ラジオボタングループを表すために使用します。
- **scrollbar** スクロールバーを表すために使用します。
- **search** テキストフィールド要素を検索フィールドとしても扱う必要がある場合に使用します。
- **spinbutton** 選択肢のリストを開くボタンを表すために使用します。
- **summary** アプリの初回起動時に、アプリの現在の状態の簡単な概要を提供するために要素を使用できる場合に使用します。
- **switch** オンとオフを切り替えられるスイッチを表すために使用します。
- **tab** タブを表すために使用します。
- **tablist** タブリストを表すために使用します。
- **text** 要素を変更できない静的テキストとして扱う必要がある場合に使用します。
- **timer** タイマーを表すために使用します。
- **togglebutton** トグルボタンを表すために使用します。ボタンがオンになっているかオフになっているかを示すために、`accessibilityState`の`checked`と共に使用する必要があります。
- **toolbar** ツールバー(アクションボタンまたはコンポーネントのコンテナ)を表すために使用します。
- **grid** ScrollView、VirtualizedList、FlatList、またはSectionListと共に使用してグリッドを表します。AndroidのGridViewにグリッドの入り/抜きのアナウンスを追加します。
accessibilityState
支援技術ユーザーにコンポーネントの現在の状態を説明します。
accessibilityState
はオブジェクトです。以下のフィールドが含まれています。
名前 | 説明 | タイプ | 必須 |
---|---|---|---|
disabled | 要素が無効になっているかどうかを示します。 | boolean | いいえ |
selected | 選択可能な要素が現在選択されているかどうかを示します。 | boolean | いいえ |
checked | チェック可能な要素の状態を示します。このフィールドは、ブール値または「mixed」文字列を使用して、中間状態のチェックボックスを表すことができます。 | boolean または 'mixed' | いいえ |
busy | 要素が現在ビジー状態かどうかを示します。 | boolean | いいえ |
expanded | 展開可能な要素が現在展開されているか折りたたまれているかを示します。 | boolean | いいえ |
使用するには、`accessibilityState`を特定の定義を持つオブジェクトに設定します。
accessibilityValue
コンポーネントの現在の値を表します。コンポーネントの値のテキストによる説明、またはスライダーやプログレスバーなどの範囲ベースのコンポーネントの場合は、範囲情報(最小、現在、最大)が含まれます。
accessibilityValue
はオブジェクトです。以下のフィールドが含まれています。
名前 | 説明 | タイプ | 必須 |
---|---|---|---|
min | このコンポーネントの範囲の最小値。 | integer | `now`が設定されている場合は必須です。 |
max | このコンポーネントの範囲の最大値。 | integer | `now`が設定されている場合は必須です。 |
now | このコンポーネントの範囲の現在の値。 | integer | いいえ |
text | このコンポーネントの値のテキストによる説明。設定されている場合、`min`、`now`、`max`をオーバーライドします。 | string | いいえ |
accessibilityViewIsModal
iOS
VoiceOverが、レシーバーの兄弟であるビュー内の要素を無視する必要があるかどうかを示すブール値です。
たとえば、兄弟ビュー A
と B
を含むウィンドウで、ビュー B
に accessibilityViewIsModal
を true
に設定すると、VoiceOver はビュー A
の要素を無視します。一方、ビュー B
に子ビュー C
が含まれていて、ビュー C
に accessibilityViewIsModal
を true
に設定した場合、VoiceOver はビュー A
の要素を無視しません。
accessibilityElementsHidden
iOS
このアクセシビリティ要素内に含まれるアクセシビリティ要素が非表示かどうかを示すブール値です。
たとえば、兄弟ビュー A
と B
を含むウィンドウで、ビュー B
に accessibilityElementsHidden
を true
に設定すると、VoiceOver はビュー B
の要素を無視します。これは、Android のプロパティ importantForAccessibility="no-hide-descendants"
と同様です。
aria-valuemax
スライダーやプログレスバーなど、範囲ベースのコンポーネントの最大値を表します。
aria-valuemin
スライダーやプログレスバーなど、範囲ベースのコンポーネントの最小値を表します。
aria-valuenow
スライダーやプログレスバーなど、範囲ベースのコンポーネントの現在の値を表します。
aria-valuetext
コンポーネントのテキストによる説明を表します。
aria-busy
要素が変更中で、支援技術が変更が完了するまで待ってからユーザーに更新を通知することを示します。
タイプ | デフォルト |
---|---|
boolean | false |
aria-checked
チェック可能な要素の状態を示します。このフィールドは、ブール値または「mixed」文字列を使用して、中間状態のチェックボックスを表すことができます。
タイプ | デフォルト |
---|---|
boolean, 'mixed' | false |
aria-disabled
要素は認識できるが、無効になっているため、編集または操作できないことを示します。
タイプ | デフォルト |
---|---|
boolean | false |
aria-expanded
展開可能な要素が現在展開されているか折りたたまれているかを示します。
タイプ | デフォルト |
---|---|
boolean | false |
aria-hidden
このアクセシビリティ要素内に含まれるアクセシビリティ要素が非表示かどうかを示します。
たとえば、兄弟ビュー A
と B
を含むウィンドウで、ビュー B
に aria-hidden
を true
に設定すると、VoiceOver はビュー B
の要素を無視します。
タイプ | デフォルト |
---|---|
boolean | false |
aria-label
インタラクティブな要素にラベルを付ける文字列値を定義します。
タイプ |
---|
string |
aria-labelledby
Android
適用されている要素にラベルを付ける要素を識別します。 aria-labelledby
の値は、関連する要素の nativeID
と一致する必要があります。
<View>
<Text nativeID="formLabel">Label for Input Field</Text>
<TextInput aria-label="input" aria-labelledby="formLabel" />
</View>
タイプ |
---|
string |
aria-live
Android
要素が更新されることを示し、ユーザーエージェント、支援技術、およびユーザーがライブリージョンから期待できる更新の種類を記述します。
- off アクセシビリティサービスはこのビューへの変更を発表すべきではありません。
- **polite** アクセシビリティサービスはこのビューへの変更を読み上げます。
- **assertive** アクセシビリティサービスは、現在読み上げている内容を中断して、このビューへの変更をすぐに読み上げます。
タイプ | デフォルト |
---|---|
enum('assertive' , 'off' , 'polite' ) | 'off' |
aria-modal
iOS
VoiceOver がレシーバーの兄弟であるビュー内の要素を無視する必要があるかどうかを示すブール値です。
タイプ | デフォルト |
---|---|
boolean | false |
aria-selected
選択可能な要素が現在選択されているかどうかを示します。
タイプ |
---|
boolean |
importantForAccessibility
Android
同じ親を持つ2つの重複するUIコンポーネントの場合、デフォルトのアクセシビリティフォーカスの動作は予測できません。 importantForAccessibility
プロパティは、ビューがアクセシビリティイベントを発生させるかどうか、およびアクセシビリティサービスに報告されるかどうかを制御することで、これを解決します。 auto
、yes
、no
、および no-hide-descendants
に設定できます(最後の値は、アクセシビリティサービスがコンポーネントとそのすべての子を無視するように強制します)。
<View style={styles.container}>
<View
style={[styles.layout, {backgroundColor: 'green'}]}
importantForAccessibility="yes">
<Text>First layout</Text>
</View>
<View
style={[styles.layout, {backgroundColor: 'yellow'}]}
importantForAccessibility="no-hide-descendants">
<Text>Second layout</Text>
</View>
</View>
上記の例では、yellow
レイアウトとその子孫は、TalkBack と他のすべてのアクセシビリティサービスに対して完全に非表示です。そのため、TalkBack を混乱させることなく、同じ親を持つ重複ビューを使用できます。
onAccessibilityEscape
iOS
2本指のZ字型のジェスチャである「エスケープ」ジェスチャが実行されたときに呼び出されるカスタム関数に、このプロパティを割り当てます。エスケープ関数は、ユーザーインターフェイスで階層的に戻る必要があります。これは、ナビゲーション階層で上または後ろに移動すること、またはモーダルユーザーインターフェイスを閉じることを意味する場合があります.選択した要素に onAccessibilityEscape
関数がない場合、システムはビュー階層を上にたどって、関数を持つビューを見つけるか、見つからないことを示すために音を鳴らします。
onAccessibilityTap
選択中にアクセシブル要素をダブルタップすることでアクティブにしたときに呼び出されるカスタム関数を割り当てるには、このプロパティを使用します。
onMagicTap
iOS
2本指でダブルタップする「マジタップ」ジェスチャが実行されたときに呼び出されるカスタム関数に、このプロパティを割り当てます。マジタップ関数は、ユーザーがコンポーネントで実行できる最も関連性の高いアクションを実行する必要があります。iPhoneの電話アプリでは、マジタップは電話に出るか、現在の電話を終了します。選択した要素に onMagicTap
関数がない場合、システムはビュー階層を上にたどって、関数を持つビューを見つけます.
role
role
は、コンポーネントの目的を伝え、accessibilityRole
プロパティよりも優先されます。
role
は以下のいずれかになります
- **alert** 要素にユーザーに提示する重要なテキストが含まれている場合に使用します。
- **button** 要素をボタンとして扱う必要がある場合に使用します。
- **checkbox** 要素が、オン、オフ、または中間状態を持つチェックボックスを表す場合に使用します。
- **combobox** 要素がコンボボックスを表す場合に使用します。コンボボックスでは、ユーザーは複数の選択肢から選択できます。
- grid ScrollView、VirtualizedList、FlatList、または SectionList と共に使用してグリッドを表します。Android GridView にグリッド内/外のアナウンスを追加します。
- heading 要素がコンテンツセクションのヘッダーとして機能する場合に使用します(例:ナビゲーションバーのタイトル)。
- img 要素を画像として扱う必要がある場合に使用します。たとえば、ボタンやリンクと組み合わせることができます。
- **link** 要素をリンクとして扱う必要がある場合に使用します。
- list アイテムのリストを識別するために使用されます。
- **menu** コンポーネントが選択肢のメニューである場合に使用します。
- **menubar** コンポーネントが複数のメニューのコンテナである場合に使用します。
- **menuitem** メニュー内の項目を表すために使用します。
- **none** 要素にロールがない場合に使用します。
- presentation 要素にロールがない場合に使用されます。
- **progressbar** タスクの進捗状況を示すコンポーネントを表すために使用します。
- **radio** ラジオボタンを表すために使用します。
- **radiogroup** ラジオボタングループを表すために使用します。
- **scrollbar** スクロールバーを表すために使用します。
- searchbox テキストフィールド要素も検索フィールドとして扱う必要がある場合に使用します。
- slider 要素を「調整」できる場合に使用します(例:スライダー)。
- **spinbutton** 選択肢のリストを開くボタンを表すために使用します。
- **summary** アプリの初回起動時に、アプリの現在の状態の簡単な概要を提供するために要素を使用できる場合に使用します。
- **switch** オンとオフを切り替えられるスイッチを表すために使用します。
- **tab** タブを表すために使用します。
- **tablist** タブリストを表すために使用します。
- **timer** タイマーを表すために使用します。
- **toolbar** ツールバー(アクションボタンまたはコンポーネントのコンテナ)を表すために使用します。
アクセシビリティアクション
アクセシビリティアクションにより、支援技術はコンポーネントのアクションをプログラムで呼び出すことができます。アクセシビリティアクションをサポートするには、コンポーネントは2つのことを行う必要があります
accessibilityActions
プロパティを介してサポートするアクションのリストを定義します。- アクションリクエストを処理するために
onAccessibilityAction
関数を実装します。
accessibilityActions
プロパティには、アクションオブジェクトのリストが含まれている必要があります。各アクションオブジェクトには、次のフィールドが含まれている必要があります
名前 | タイプ | 必須 |
---|---|---|
name | string | はい |
label | string | いいえ |
アクションは、ボタンのクリックやスライダーの調整などの標準アクション、またはメールメッセージの削除など、特定のコンポーネントに固有のカスタムアクションを表します。 name
フィールドは標準アクションとカスタムアクションの両方で必須ですが、label
は標準アクションではオプションです。
標準アクションのサポートを追加する場合、name
は次のいずれかである必要があります
'magicTap'
- iOSのみ - VoiceOverフォーカスがコンポーネント上または内部にある間に、ユーザーが2本指でダブルタップしました。'escape'
- iOSのみ - VoiceOverフォーカスがコンポーネント上または内部にある間に、ユーザーが2本指のスクラブジェスチャ(左、右、左)を実行しました。'activate'
- コンポーネントをアクティブにします。これは、支援技術の有無にかかわらず、同じアクションを実行する必要があります。スクリーンリーダーユーザーがコンポーネントをダブルタップすると実行されます.'increment'
- 調整可能なコンポーネントを増分します。iOSでは、コンポーネントのロールが'adjustable'
で、ユーザーがフォーカスを置いて上にスワイプすると、VoiceOverはこのアクションを生成します。Androidでは、ユーザーがコンポーネントにアクセシビリティフォーカスを置いて音量アップボタンを押すと、TalkBackはこのアクションを生成します。'decrement'
- 調整可能なコンポーネントを減分します。iOSでは、コンポーネントのロールが'adjustable'
で、ユーザーがフォーカスを置いて下にスワイプすると、VoiceOverはこのアクションを生成します。Androidでは、ユーザーがコンポーネントにアクセシビリティフォーカスを置いて音量ダウンボタンを押すと、TalkBackはこのアクションを生成します。'longpress'
- Androidのみ - このアクションは、ユーザーがコンポーネントにアクセシビリティフォーカスを置き、画面上で1本の指をダブルタップして押し続けると生成されます。これは、支援技術の有無にかかわらず、同じアクションを実行する必要があります。
label
フィールドは標準アクションではオプションであり、支援技術では使用されないことがよくあります。カスタムアクションの場合、これはユーザーに提示されるアクションの説明を含むローカライズされた文字列です。
アクションリクエストを処理するには、コンポーネントが onAccessibilityAction
関数を実装する必要があります。この関数の唯一の引数は、実行するアクションの名前を含むイベントです。RNTesterの以下の例は、複数カスタムアクションを定義および処理するコンポーネントを作成する方法を示しています。
<View
accessible={true}
accessibilityActions={[
{name: 'cut', label: 'cut'},
{name: 'copy', label: 'copy'},
{name: 'paste', label: 'paste'},
]}
onAccessibilityAction={event => {
switch (event.nativeEvent.actionName) {
case 'cut':
Alert.alert('Alert', 'cut action success');
break;
case 'copy':
Alert.alert('Alert', 'copy action success');
break;
case 'paste':
Alert.alert('Alert', 'paste action success');
break;
}
}}
/>
スクリーンリーダーが有効になっているかどうかの確認
AccessibilityInfo
APIを使用すると、スクリーンリーダーが現在アクティブになっているかどうかを判断できます。詳細は、AccessibilityInfoドキュメントを参照してください。
アクセシビリティイベントの送信Android
UIコンポーネントでアクセシビリティイベントをトリガーすると便利な場合があります(たとえば、カスタムビューが画面に表示されたとき、またはビューにアクセシビリティフォーカスを設定したとき)。ネイティブUIManagerモジュールは、この目的のために `sendAccessibilityEvent` メソッドを公開しています。これは、ビュ タグとイベントタイプの2つの引数を取ります。サポートされているイベントタイプは、typeWindowStateChanged
、typeViewFocused
、および typeViewClicked
です。
import {Platform, UIManager, findNodeHandle} from 'react-native';
if (Platform.OS === 'android') {
UIManager.sendAccessibilityEvent(
findNodeHandle(this),
UIManager.AccessibilityEventTypes.typeViewFocused,
);
}
TalkBackサポートのテストAndroid
TalkBackを有効にするには、Androidデバイスまたはエミュレータの「設定」アプリに移動します。「アクセシビリティ」をタップし、次に「TalkBack」をタップします。「サービスを使用」スイッチを切り替えて、有効または無効にします。
Androidエミュレータには、デフォルトでTalkBackがインストールされていません。Google PlayストアからエミュレータにTalkBackをインストールできます。Google Playストアがインストールされているエミュレータを選択してください。これらはAndroid Studioで入手できます。
音量キーのショートカットを使用してTalkBackを切り替えることができます。音量キーのショートカットを有効にするには、「設定」アプリに移動し、「アクセシビリティ」を選択します。一番上で、音量キーのショートカットを有効にします。
音量キーのショートカットを使用するには、両方の音量キーを3秒間押して、アクセシビリティツールを起動します。
さらに、必要に応じて、コマンドラインからTalkBackを切り替えることもできます。
# disable
adb shell settings put secure enabled_accessibility_services com.android.talkback/com.google.android.marvin.talkback.TalkBackService
# enable
adb shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService
VoiceOverサポートのテストiOS
iOSまたはiPadOSデバイスでVoiceOverを有効にするには、「設定」アプリに移動し、「一般」をタップしてから「アクセシビリティ」をタップします。そこには、デバイスを使いやすくするための多くのツールがあり、VoiceOverも含まれています。VoiceOverを有効にするには、「視覚」の下にある「VoiceOver」をタップし、上部に表示されるスイッチを切り替えます。
アクセシビリティ設定の一番下に、「アクセシビリティショートカット」があります。これを使用して、ホームボタンをトリプルクリックすることでVoiceOverを切り替えることができます。
VoiceOverはシミュレータでは使用できませんが、XcodeのAccessibility Inspectorを使用して、アプリケーションを通じてmacOSのVoiceOverを使用できます。macOSのVoiceOverは異なる体験になる場合があるため、常にデバイスでテストすることをお勧めします。