背景
- 以前Androidのアクセシビリティを調査したことがあり、まだあまり知られていないことがたくさんあると感じているので少しでも情報を出していこうと思う。
- ちなみにAndroidアプリのアクセシビリティガイドラインはココにありますMaking Apps More Accessible(英語)
Androidのアクセシビリティ機能
- 設定→ユーザ補助から各種機能をON/OFFできる
- TalkBack(音声読上げ機能)、フォントサイズ指定、拡大表示、字幕、色補正(色弱)、色反転等がある
- 本記事では特にアプリケーション開発上考慮しなければならないTalkBack, フォントサイズ指定機能について取り上げる
TalkBackとは?
- 目の不自由なユーザ向けのAndroid標準搭載支援ツール。タップした場所あるいはフォーカスが当たった場所を音声で読上げる機能を有する。ONにすることによりタッチ操作体系も変わり、シングルタップでフォーカス、ダブルタップで確定、画面スクロールは二本指での操作となる
TalkBackをONにされたときにアプリが気をつけるべきこと
ContentDescriptionをきちんと書く
- TalkBackは音声読み上げ機能があるが、ViewのcontentDescriptionが記載されていないとImage等テキスト情報がないものは読み上げてくれない
- EditTextはhint属性を設定することで読み上げ可能
- TextViewはcontentDescriptionを設定しなくても設定されているTextを読み上げてくれる
- SurfaceViewを使っていると、読み上げてくれないので自分で読み上げる必要がある
- WebViewも読み上げるところ、読み上げないところがあるのでちゃんと確認する
- lintをかけるとMissing contentDescription attribute on imageが出ることがある
- Image以外でも表示されているテキストより詳細をここに記載しておくことで読み上げ時にわかりやすくすることができる
- contentDescriptionには必要最低限の説明を記載すること
例) Googleのサンプルから抜粋(https://developer.android.com/guide/topics/ui/accessibility/apps)
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:contentDescription="@string/share"
android:src="@drawable/ic_share" />
ImageView playPauseImageView = new ImageView();
boolean mediaCurrentlyPlaying = true;
...
private void updateImageButton() {
if (mediaCurrentlyPlaying) {
playPauseImageView.setImageResource(R.drawable.ic_pause);
// In res/values/strings.xml, "pause" contains a value of "Pause".
playPauseImageView.setContentDescription(getString(R.string.pause));
} else {
playPauseImageView.setImageResource(R.drawable.ic_play);
// In res/values/strings.xml, "play" contains a value of "Play".
playPauseImageView.setContentDescription(getString(R.string.play));
}
}
キーボードでも操作できるようにする
- TalkBackを有効にするとフォーカスありきの操作体系に変わる。そのため、操作できるGUI部品にはフォーカスできるようにしておかないといけない。また、操作できないラベルなどもフォーカスが当たり読み上げられることを確認する必要がある
- 具体的にはfocusable属性をtrueにする
AccessibilityEventを発生させる
- 任意のタイミングで読み上げを行うにはAccessibilityEventを発生させることができる
例)
public void sendAccessibilityEvent(String text, View source) {
AccessibilityManager manager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
if(manager.isEnabled()){
AccessibilityEvent event = AccessibilityEvent.obtain();
event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
event.setClassName(getClass().getName());
event.getText().add(text);
event.setSource(source);
manager.sendAccessibilityEvent(event);
}
}
TalkBackのON/OFFをチェックして広告をオフにする
-
広告は目の見えない、もしくは見えにくい人にとっては間違って触った時にもう戻ってこれなくなる上、危険なサイトに誘導されてしまう可能性のある非常に厄介なものになりうる。非表示にすると当然クリックしてもらえなくなるが、アクセシビリティを優先すべきと考える。
-
AccessibilityManagerのisEnabled(), isExploreByTouchEnabled()あたりを使うとTalkBackのON/OFFをチェックできる。
AccessibilityManager am = (AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE);
boolean isAccessibilityEnabled = am.isEnabled();
boolean isExploreByTouchEnabled = am.isTouchExplorationEnabled();
TalkBack以外で気をつけること
文字を大きくする、設定で文字を大きくしてもレイアウトが崩れないようにする
- Android標準設定でフォントサイズを変更する機能がある
- 設定→ディスプレイ→フォントサイズから変更可能
-
アプリは設定でフォントサイズが変えられることを想定してつくらないとレイアウトが崩れる、文字が切れて見えなくなるなどの不具合になる
例) ※キャプチャ画像は2018/03/30時点のものですでに修正されている可能性あり
-
根本解決ではないが設定の影響を受けなくする方法
- spではなくdpを使う
- 設定に関わらずフォントサイズを固定したい場合はフォントサイズ指定をspではなくdpにすると良い。ただし、端末のフォントサイズ設定に合わせてアプリも文字を可変にするのが本来あるべき姿なので、lintに怒られることになる
- spではなくdpを使う
背景黒地に白文字にする
- コントラスト強調され、こちらの方が見やすいという人がいる。参考ページは以下
- iPhone(iOS10)、Android 5.0 以降の設定にもある、OSレベルで反対色(反転色、補色ではない)にするのでアプリ単位で気にする必要はない
- OSレベルで勝手に変えられるのでUDを意識して黒地に白フォントで作成していたアプリは逆に見にくくなってしまう、アプリ作成者は反転ONにしてテストした方がよさそう
- Androidのこの機能は Android 7.1.2 現在まで試験運用という位置付けでパフォーマンスにも影響があると記載があるが、Nexus 5XでPokemon Goを動かしてみた限りでは特に影響なさそうに感じた
音声読み上げ機能を付ける(TalkBackをOffにしている前提)
- TalkBackをONにしていなくても音声読み上げをがあったほうがいい場合がある、老眼で細かい字を読みにくくなった人向け、外出中使用を想定してない場合は音声出力しても問題ない
- Androidの場合、TTS(TextToSpeech)機能を利用する
- 昔は日本語に対応していなく、N2TTS等を別途インストールする必要があったが、最近のAndroid(6.0から?)では日本語読み上げをサポートしている
- 読み上げスピードには変えられると良い、視覚障害者で慣れた人はかなり早くても瞬時に認識することができる