【iOS】VoiceOver対応の実装方法 - 基本的な使い方
最低限の実装だけで自然な読み上げを作る(SwiftUI)
動作確認編はこちら → 【iOS】VoiceOverの動作確認方法 - シミュレータですぐ試せる
VoiceOver 対応は少し難しそうに見えるかもしれませんが、
実は やるべきことが決まっている ので、ポイントさえ押さえれば十分自然な読み上げが実現できます。
まずは “やらなくていいこと” と “やるべきこと” を分けるところから始めましょう。
🎯 基本の考え方
VoiceOver のために伝える情報は次の 3 つだけです。
- label:その要素が何を意味するか
- hint:操作したときに何が起こるか
- value:現在の状態・数値
この 3 つを“必要なところにだけ”付ければ十分です。
まずは「何もしなくていい」要素
SwiftUI の標準コンポーネントは、アクセシビリティがかなり整っているため、
まずは 手を入れなくてよい部分 を明確にします。
基本的にはそのままでOK
- Text → テキストをそのまま読んでくれる
- Button → ラベルを理解して「◯◯、ボタン」と読まれる
- Toggle → オン/オフを自然に伝えてくれる
- TextField → 多くの場合、プレースホルダーをラベルとして扱う
ここに無理に手を加える必要はありません。
手を入れるべき要素(ここを押さえれば十分)
VoiceOver 対応の仕上がりに大きく影響するのは次の 3 つです。
- Image / SF Symbols(意味のある画像)
- Button を使っていない“ボタン風の View”
- 複数の要素を 1 つのまとまりとして伝えたい View
ここを改善するだけで、多くの UI は自然に扱えるようになります。
.accessibilityLabel() — 意味を伝えるためのラベル
ラベルは 見た目ではなく“意味”を伝える のが大切です。
意味のある画像にラベルを付ける
Image("yarn")
.accessibilityLabel("編み物のイラスト")
アイコン+テキストをひとまとまりにする
VStack {
Image(systemName: "heart.fill")
Text("お気に入り")
}
.accessibilityElement(children: .combine)
.accessibilityLabel("お気に入り")
combine を使うことで、
2つの要素を1つの読み上げ対象として自然に扱える ようになります。
.accessibilityHint() — 必要なときだけ使う
ヒントは VoiceOver に 毎回読み上げられる ため、使いどころが重要です。
付ける価値がある例
Button("作品を記録する") { }
.accessibilityHint("新しい作品を追加します")
不要な例(自明)
Button("作品を記録する") { }
.accessibilityHint("作品を記録します") // これは不要
“押したあと何が起きるか想像しにくい場面” に絞って使います。
.accessibilityValue() — 数値や状態を明確にする
- 進捗
- 件数
- 選択状態
- 日付
などに適しています。
ProgressView(value: progress)
.accessibilityLabel("進行状況")
.accessibilityValue("\(Int(progress * 100))%")
.accessibilityHidden(true) — 装飾は読ませない
意味を持たない装飾画像は読み上げても情報にならないため、
VoiceOver の利用者にとって負担になることがあります。
Image("background")
.accessibilityHidden(true)
ただし、状態を表すアイコン(エラーなど) は label を付けて伝えます。
.accessibilityElement(children:) — 複数要素をまとめて扱う
複数の要素が「見た目としても意味としても 1 つのまとまり」なら、
VoiceOver にとっても 1 つとして扱われたほうが理解しやすくなります。
よく使うのは .combine / .contain です。
実践例:複数要素を “まとまり” として扱う
アイコン+見出し+説明+ボタンの構成を例に
VStack(spacing: 24) {
Image(systemName: "sparkles")
.accessibilityHidden(true) // 装飾的なため読み上げない
Text("はじめての作品を記録しましょう")
.font(.headline)
Text("編んだ作品を管理できます")
.font(.body)
Button("作品を記録する") { }
}
.accessibilityElement(children: .contain)
VoiceOver の読み上げ順は自然に:
- 見出し
- 説明文
- ボタン
という流れになります。
最低限の判断基準(これだけ覚えればOK)
- 意味がある → label
- 自明 → hint は付けない
- 状態・数値 → value
- 装飾 → hidden
- まとまりを 1 つとして扱いたい → combine / contain
無理に全部使う必要はなく、
“必要な場所に必要な情報だけ” を追加するイメージで十分です。
関連記事・参考資料
動作確認の方法はこちら
Apple公式ドキュメント
- Framework: Accessibility
https://developer.apple.com/documentation/accessibility - Assistive Technology: VoiceOver
https://developer.apple.com/documentation/accessibility/voiceover - API Collection: Accessibility fundamentals
https://developer.apple.com/documentation/swiftui/accessibility-fundamentals - API Collection: Accessibility modifiers
https://developer.apple.com/documentation/swiftui/view-accessibility - Developer Tool: Accessibility Inspector
https://developer.apple.com/documentation/accessibility/accessibility-inspector - Human Interface Guidelines – Accessibility
https://developer.apple.com/jp/design/human-interface-guidelines/accessibility/
Discussion