Androidアプリのアクセシビリティを向上させるために、必要なこと

主にAndroid、たまにiOSのアプリ開発を担当している髙坂(id:k3n)です。

唐突ですが、この記事をご覧になっている皆様が開発に携わっているアプリは、Accessibleでしょうか。アクセシビリティと一口に言っても、TalkBackのような視覚に頼らないアプリの操作方法をサポートすることであったり、前景色(文字色など)と背景色とのコントラスト比を十分に持たせて視認しやすい色使いにしたり、ボタンのタッチ領域を十分に広くしてボタン操作を容易にするなど、様々なことが関係してきます。

この記事をご覧になっているということは、少なからずアクセシビリティに対する興味・関心を持っていらっしゃると思います。僕自身は、Androidアプリを開発していて、「ImageViewのcontentDescriptionが設定されていないよ」というLint warningを無視するためにtools:ignore="ContentDescription"を機械的に実装することにモヤモヤしていたことが興味を持つきっかけでした。

弊社には、主にデザイナ・エンジニアを中心にアクセシビリティに強い関心を持つメンバーがいます。さらに、とてもありがたいことに、会社としてもAccessibleなアプリを作れるということを強みの一つにしていこうよ!ということで、業務の一環として、Androidアプリを開発するにあたってアクセシビリティを向上させるためにはどういったことに心を配れば良いのかについて、調査する機会をいただけました(iOSアプリに関してまとめた記事はこちらです)。

本記事では、Androidアプリを開発するにあたって、アクセシビリティを向上させるために何を考慮し、何が必要となるのかを以下の観点をベースにまとめます。

  • エンジニアは、何を考慮する必要があるのか
  • エンジニアが実装するにあたり、デザイナからどのようなインプットが必要となるのか
  • 適切に実装できていることを、どのように確認するのか

本題に入る前に、アプリのアクセシビリティを向上させる上で念頭においていただきたいことがあります。

障碍を持つ人のためだけに対応するのではない。あらゆる人が、どのような環境でも等しく情報を得られるために対応する。

人は誰しも歳を取ります。歳を重ねる中で、目が見えづらくなったり、細かな作業がしづらくなります。あるいは、直射日光下で画面の照り返しがキツく、画面上に表示された情報を視認することが困難なこともあるでしょう。アクセシビリティを向上させることで、より簡単にアプリを操作するための方法を提供できたり、アプリの利用が厳しい環境下でも快適に利用していただけます。僕たちが作り上げたアプリが、より多くの人たちに利用され、より永く愛されるものとなります。

なお、AndroidやiOSで、OSが提供する標準的なコンポーネントを利用していれば、ある程度は自動的にアクセシビリティサービス(例えばTalkBackなど)に対応してくれます。ですが、「ある程度」と書いた通り、この対応は完全ではなく、開発時にアクセシビリティを考慮することは不可欠です。考慮が欠けた場合、アクセシビリティサービスを介してアプリを操作した場合、エンジニアが意図しない動作が引き起こされる可能性があります。クオリティの高いアプリを作る上で、アクセシビリティの考慮は欠かすことができないと思います。

前置きが長くなりました。ここからは、以下の流れで説明していきます。

TalkBackを用いた読み上げ対応

Android OSがインストールされたデバイスでは、TalkBackというスクリーンリーダシステムを利用できます。このシステムは、以下手順によって有効にし、利用を開始できます。

  1. 設定(Settings)アプリを開く
  2. ユーザー補助(Accessibility)を選択する
  3. スクリーンリーダー(Screen readers)の下にあるTalkBackを選択する
  4. サービスの使用(Use service)をONに

TalkBackという設定項目が存在しない場合は、PlayストアにあるAndroid ユーザー補助設定ツール(Android Accessibility Suite)をインストールすることで、設定項目が表示されるようになるはずです。TalkBackを使用することで、ユーザは画面上のコンポーネントをタップしたり、スワイプすることによってフォーカスを移動でき、フォーカスされたコンポーネントがシステムによって読み上げられます。

ロービジョンの方にとって有用であることはもちろんですが、視力が良い人であっても、直射日光による照り返しがキツい環境ではスマートフォンの画面が反射して表示された内容が見辛い場合がありますし、電車内等でスマートフォンを取り出せない状況があると思います。このような場合でも、TalkBackを用いることでアプリの操作が可能になります。アプリを利用できる機会が増えることに繋がります。是非対応したいですね!

TalkBackに対応する上で、以下のことに気を配る必要があります。ここからは、それぞれの項目について説明していきます。

  • 読み上げられる文言の付与
  • Viewのグルーピング
  • Live Regionを用いた、動的な変更の自動読み上げ
  • Custom Viewの対応

読み上げられる文言の付与

OSが提供するコンポーネントを利用している場合、ImageViewやImageButtonなど一部のケースを除いて、エンジニアが読み上げられる文言を設定せずとも適切に読み上げてくれます。具体的には、TextViewや、文言の設定されたButton、TextViewなどによる文言を内包するリストアイテムなどは、表示されている文言を読み上げてくれます。

エンジニアが読み上げられる文言を意識しないといけないのは、以下のケースです。

  • 画像のみのView(ImageViewやImageButtonなど)
  • 意味のある画像を併記したView(外部ブラウザ遷移を示すアイコンが文言の後に付与されているボタン)
  • 表示されている文言をそのまま読み上げても、ユーザに意味が伝わらないView(リスト中で何番目にあるのかに意味があったり、文言以外、例えば枠線色で意味を持たせているような、視覚に依存した情報提示をしているView)

読み上げられる文言の付与に際し、エンジニアは以下を考慮する必要があります。

  • 動的に表示内容が変化するViewは、レイアウトファイルではなくロジックコードで、読み上げられる文言を動的に構築し設定する必要がある
  • 読み上げる対象のViewがある場合、ハードウェアキーボードユーザに配慮するため、ImageViewなどのfocusableをtrueに設定し、キーボード操作によってもフォーカスできるよう実装しないといけない場合がある
  • タップ操作を受け付けない想定のViewがTalkBackからタップ操作可能と認識され、「ダブルタップすると有効になります。」と意図せず読み上げられていないか
    • 不用意にisClickableがtrueになっていないか、クリックイベントリスナが登録されていないかを確認する必要がある
    • 使用するライブラリによっては、デフォルト実装でisClickableがtrueになっている場合がある(例えば、GroupieのBindableItemは、デフォルトでisClickableがtrue)。この場合、継承先のクラスをタップ操作無効とするためにisClickableをfalseとするような実装を追加する必要がある
  • ViewGroupを継承して作り込まないといけないようなデザインの場合、OSが提供するコンポーネントを用いたデザインにできないかデザイナに相談する
    • OSが提供するコンポーネントであれば、あらかじめアクセシビリティサービスに配慮した実装となっているため、文言の読み上げの後、「ボタン」等のコンポーネント種別を読み上げてくれたりします。自分でViewを作り込む場合は、この辺りも自作しないといけません
  • 課金など条件をクリアしないとアクセスできない仕様のコンテンツに対し、TalkBack等のアクセシビリティサービスによってアプリを操作した場合に、不正にアクセスできる状態にないか(例えば、有料会員しか読めないニュース本文を画面に表示し、その上にグレー背景をオーバーレイし有料会員登録を促す画面をモーダル表示している場合、TalkBackの左右フリックで読み上げるViewを変えていくと、会員登録せずともニュース本文の全文を読み上げられる)1

エンジニアが対応するにあたって、デザイナから以下のインプットが必要となります。

  • 読み上げる必要のある画像に対する文言
    • 同じ意味を持つ文言がViewに併記されているなら、読み上げられる文言を重複して設定する必要はありません
  • 表示されている文言とは異なる文言を読み上げて欲しい場合は、その文言

実装についてですが、まずresディレクトリ内にあるstrings.xmlに読み上げられる文言を定義したのち、レイアウトファイルやロジックコードにて、読み上げられる文言を設定したいViewのcontentDescriptionに先ほど定義した文言を設定します。読み上げられる文言の付与が不要な場合は、contentDescriptionnullを設定する(レイアウトファイルなら、android:contentDescription="@null")か、minSdkVersionが16以上(minSdkVersion => 16)であればandroid:importantForAccessibility="no"を設定すると良いです。

読み上げられる文言は、以下の各点を押さえたものであることが望ましいです。

  • 簡潔であること
    • 特に、点字ディスプレイを利用されているユーザの場合、一度に表示できる文字数が16〜40文字程度と制限される(点字ディスプレイの機種による)ため
  • 物理的な操作方法を示す文言(クリック、タップ、押下など)を含めないこと
    • アクセシビリティサービス側がこの辺りの面倒を見てくれます。Switch AccessやVoice Accessなどを利用されているユーザは、画面を物理的にタッチしないため、これらの文言が適切ではない場合があります
  • 文脈的に最も重要な情報を、読み上げられる文言の先頭に持ってきていること
    • 読み上げられる文言をいちいち最後まで再生させる必要がなくなるため、より速く、より快適にアプリを利用していただけます

Viewのグルーピング

Viewを実装する際に、TalkBackにどの順序で読み上げて欲しいのか、デザイナと認識を合わせておく必要があります(例えば、画像を四つタイル状に並べるViewGroupで、左から右・上から下に読み上げさせるのか、もしくは上から下・左から右に読み上げさせるのか)。この認識に沿ってViewの階層構造を作らないと、実際に読み上げさせた際に読み上げ順序が想定と異なる挙動を示す可能性があります。

また、Viewが適切にグルーピングされていない場合、小項目を一つずつなぞっていくしか読み上げを進める方法がなく、小項目の要素数が多いと操作性が悪くなります。例えば、複数の曲情報が表示されるような画面で、曲単位でのグルーピングがなされていない場合、曲名だけで探す、といったことができず、各曲の曲名やアーティスト情報などを一つずつ読み上げていかなければなりません。

Viewをグルーピングする場合、android:focusableをtrueにしたViewGroup(LinearLayoutやConstraintLayoutなど)でTextViewなどの子Viewを囲います。子Viewのandroid:focusableをfalseにすることで、グループ単位での読み上げが実現できます。

また、特定のViewが見出しとしての役割を持つ場合は、android:accessibilityHeadingをtrueにすると良いです。これにより、見出し単位での読み上げの移動が可能となります。

以上を踏まえて、Viewのグルーピングに際してエンジニアは以下を考慮する必要があります。

  • Viewの階層構造と読み上げ順序が一致していること
    • 上から下・左から右という読み上げ順序から乖離したデザインの指示(読み上げの順序が直線的ではない、とか、下から上・右から左に読み上げさせようとしている)をデザイナからいただいた場合、デザインに根本的な問題がある可能性があるため、デザイナと対応を相談する必要があります
  • 関連するViewをまとめて読み上げさせたい場合は、android:focusableをtrueにしたViewGroupでこれらViewを囲い、囲った内部のViewのandroid:focusableをfalseに指定する
  • 見出しとして読み上げさせたい場合は、android:accessibilityHeadingをtrueにする
    • 段落間や単語間ではなく、見出し間での読み上げの移動が可能となります

エンジニアが対応するにあたって、デザイナから以下のインプットが必要となります。

  • 読み上げ順序が不明瞭な箇所に対する、順序の指定
  • 塊で読み上げて欲しい箇所があれば、その部分の明示
  • 塊を、その子Viewが持つ文言ではなく別の文言で読み上げて欲しい場合は、その読み上げ文言の指定
  • 特定のViewを見出しとして読み上げて欲しい場合は、その部分の明示と、読み上げ文言の指定

Viewの階層構造やViewのグルーピングに関して、以下の各点を押さえておくと良いでしょう。

  • Viewの階層構造と、画面上で見えるViewのグルーピングと、読み上げられる順序を考慮する
    • デザイナは、上から下・左から右という直線的な順序で自然に読み上げられるようデザインする
    • エンジニアは、デザイナと認識を合わせた読み上げ順序となるよう意識し、View階層を実装する
  • 複数のViewを塊として読み上げさせたい場合は、それらViewをnon-focusableにした上で、focusableなViewGroupでまとめる
  • 関連するViewを論理的にまとめようとすると、ViewGroupを入れ子にせざるを得ない時がある

Live Regionを用いた、動的な変更の自動読み上げ

ここまでの説明で扱ってきたものは、いずれもユーザが明示的にフォーカスを当てたものをTalkBackで読み上げさせるものでした。

これとは異なり、ある操作を起点として動的に表示内容が更新されるView(Viewの表示・非表示、Buttonの有効・無効など)がある場合、更新後の内容を自動的に読み上げて欲しい場合があります。これを実現するためには、TalkBackのLive Regionを用います。

動的な変更を自動的に読み上げて欲しいViewに対し、android:accessibilityLiveRegionpoliteassertiveのいずれかを設定します。politeを設定した場合は、他のViewが読み上げ中であれば、その読み上げが完了次第Live Regionを設定したViewが自動的に読み上げられます。assertiveを指定した場合は、他のViewが読み上げ中であれば、それに割り込む形でLive Regionを指定したViewが自動的に読み上げられます。

Viewが頻繁に更新されるような場合、Live Regionを用いるとユーザに混乱を生じさせ、アプリが使い物にならなくなる可能性があります。濫用を避けて、本当に必要な場合にのみ用いるよう、心がける必要があります。

Custom Viewの対応

OSが提供するコンポーネント(ButtonやTextViewなど)は標準でアクセシビリティサービスへのサポートがなされており、エンジニア側で特別な対応をせずとも、そのViewの状態や、Viewの種別などを読み上げてくれます。ViewやCanvasなどからCustom Viewを自作するのに比べて、これらコンポーネントを拡張してCustom Viewを作成した方が、アクセシビリティサービスに対応するために追加で必要となる実装を減らせるため、可能な限り、頑張って自作しない方針に寄せることが望ましいです。

Custom Viewの対応についての説明は省きます。以下リファレンスを参考に、アクセシビリティサービスに対応するための実装を追加していくことになるかと思います。

タッチ領域の確保

操作対象のViewのタッチ操作可能な領域が狭いと、多くの人にとって操作がしづらくなります。特に指が太かったり、運動技能が低下している場合や、スクリーンリーダーのユーザでタッチ操作によりアプリを操作している場合、これが顕著になります。

Viewが実際にどれだけの画面領域を持っているかを視覚的に知るためには、以下の操作によりレイアウト境界を表示(Show layout bounds)を有効にすると良いでしょう。

  1. 設定(Settings)アプリを開く
  2. システム(System)を選択する
  3. 開発者向けオプション(Developer Options)を選択する
  4. レイアウト境界を表示(Show layout bounds)をONに

タッチ操作可能な領域は、最低でも 48dp × 48dp のサイズを確保すべきです2。もちろん、これよりさらに大きければ、さらに良いです。

タッチ操作可能な領域を拡大させる方法としては、以下の方法があります。いずれの方法を用いても、似た結果となります。

  • minWidthminHeightを指定する
  • paddingを追加する
  • TouchDelegate APIを用いる

また、複数のタッチ操作可能なViewが隣接している場合、情報の密度と操作性のバランスをとるため、最低でも 8dp の余白を設けるべきです。

以上を踏まえ、アプリを実装する際に、エンジニアは以下の項目に配慮すると良いです。

  • 小さい画像のみのボタンや、縦あるいは横に狭いボタンを実装する場合、タッチ操作可能な領域が十分に確保できているか(48dp × 48dp)を確認する
  • タッチ操作可能なViewが隣接する場合、それらの間隔が詰まり過ぎていないか(8dp)を確認する

デザイナは、以下を考慮してアプリをデザインすると良いです。

  • タッチ操作可能なボタン等は、最低でも 48dp × 48dp の表示領域が確保できるよう、隣接するViewとの間隔を調整すること
    • 特に、タッチ操作可能な小さいアイコン類は、この点が守られていることを確認する
  • タッチ操作可能なViewが複数隣接している場合、これらの間隔が 8dp 以上空いていること

フォントサイズの指定方法

スマートフォンやブラウザには、システム全体のフォントサイズを変更する機能があります。もちろんAndroid OSを搭載したデバイスもこれの例外ではありません。

読みやすさを向上させるため、ユーザはこの機能を用いてシステムのフォントサイズを拡大させる可能性があります。ですが、アプリ側でフォントサイズが拡大されることを考慮した実装をしておかないと、システムのフォントサイズ設定でフォントサイズを拡大したにも関わらず、アプリ上のフォントサイズにこれが反映されなかったり、あるいはフォントサイズ変更に伴ってアプリのレイアウトが崩れてしまう可能性があります。

アプリを実装する際に、エンジニアは以下の項目を配慮すると良いです。

  • システムのフォントサイズ設定に依存して欲しくない、という特殊な場合を除き、フォントサイズの指定にはspを用いる
  • フォントサイズを変更した場合、または表示する文字数が多い場合にレイアウトが崩れないかを確認する
    • 特に、フォントサイズを変更して文字が見切れる場合は、文字を省略するか(省略するならどこを省略するのかまで含めて)、改行するかをデザイナに確認する3

また、エンジニアが対応するにあたって、デザイナから以下のインプットが必要となります。

  • フォントサイズの指定にsp以外(例えばdp)を用いる場合、それがエンジニア側に分かるように示す。また、sp以外を用いる理由を説明する
  • 文字数が多い場合、またはフォントサイズが変更されたことによってViewから文字が見切れてしまう場合の対応方針
    • 文字を折り返して複数行で表示するのか、文字の一部を省略して1行で表示するのか
    • 省略するなら、先頭・中間・末尾のどの位置で省略するのか

コントラスト比の確保

前景色(文字色など)と背景色のコントラスト比が十分でない場合、ロービジョンの方や、直射日光下で画面の照り返しがキツい場合などで画面上の情報を読み取ることが困難になります。

WCAG 2.14では、文字画像を含むテキストに対し、大文字や太字の場合は最低限のコントラスト比を3:1、非アクティブなViewの一部・装飾目的・誰も視認できない・重要な他の視覚的なコンテンツを含む写真の一部・ロゴタイプ、という条件に当てはまらないものについて最低限のコントラスト比を4.5:1とし、これに適合するか超えるように色を設定すべきだとしています(参考)。

また、コンテンツを理解するために必要なアイコン等の画像については、少なくとも3:1のコントラスト比が求められています(参考)。

これと同様のことが、Material DesignのAccessibility/Color and contrastや、Android DevelopersのMake apps more accessible/Increase text visibilityにも記載されています。特に、Android Developersのドキュメントでは、以下のように記載されています。

  • テキストが 18pt よりも小さい場合、またはテキストが太字で 14pt より小さい場合、色のコントラスト比は 4.5:1 以上にする必要があります
  • それ以外のテキストの場合、色のコントラスト比は 3.0:1 以上にする必要があります

アプリを実装する際に、エンジニアは以下の項目を確認すると良いです。

  • 画像の上に文字を置くようなレイアウトの場合、画像の色と文字色の組み合わせによってはコントラスト比が下がる可能性がある。このようなレイアウトの指示がある場合は、コントラスト比を保つ方法をデザイナと相談する
  • ボタンにフォーカスが当たった際に、特定の色をのせてフォーカスされていることを示すレイアウトになっている場合、色がのることでコントラスト比が下がる可能性がある(例えば、黒文字のボタンでフォーカス時に透過グレーをボタンにのせる、とか)。このようなレイアウトの指示を見つけたら、デザイナにコントラスト比を考慮できているか確認を取る

コントラスト比に関しては、デザイナ側からいただいたレイアウトの指示において、既に考慮がなされている想定です。そのため、エンジニアが対応するにあたってデザイナから別段のインプットは不要です。

色以外での手がかりの提供

色に情報を持たせている場合(例えば外部リンクであることを示すために、文字色を青色にする)、色以外でもその情報が認識できるような手がかりを加えるべきです(例えば、テキストに下線を引く)。色弱の方や、直射日光下で画面の照り返しがある等の状況下で色の識別が難しい場合でも、色以外の手がかりを提供することで、情報の認識が容易となります。

アプリを実装する際に、エンジニアは以下の項目に配慮すると良いです。

  • 色のみに情報を持たせているViewがないかを確認し、あれば色以外でも情報を認識できる手がかりを加える
    • 例えば、外部リンクを示すテキストに対しては、文字色を変えるだけではなく、下線を引く
    • 例えば、入力値にエラーがあることを示す場合、色で示すだけではなく、テキストでもエラーであることを示す
    • アイコンの色のみでステータスを示すようなものがあれば、アイコンの形も変えるようデザイナに伝える

デザイナは、以下を考慮してアプリをデザインすると良いです。

  • 色しか手がかりのない情報の示し方は避ける

適切に対応できていることを確認する方法

ここまでで説明してきた各項目について、適切に対応できているかを確認するための方法を記します。

TalkBack

実際にTalkBackを起動し、読み上げさせて動作を確認するのが良いです。ユーザー補助検証ツール(Accessibility Scanner)を用いることで、読み上げられる文言が適切に付与されているか、Viewタイプや状態を含む文言が付与されていないか、視覚的順序と読み上げ順序が一致しない状態になっていないか等の確認が可能ですが、指摘の精度は高くなく、指摘漏れ等が見受けられる印象です。そのため、このツールを用いた検査は簡易的なものと考え、あくまで実際にTalkBackを利用した検査を主体とするのが望ましいでしょう。

実際にTalkBackで読み上げさせて、特に以下の現象が発生しないかを確認するのが良いでしょう。

  • ボタン等のタップ操作可能なViewであるにも関わらず、「ダブルタップすると有効になります。」の読み上げがなされない状態になっていないか。また逆にタップ操作不能なViewであるにも関わらず、この文言が読み上げられていないか
  • 読み上げられる文言が適切か。アセットのファイル名がそのまま読み上げられる等の不正な挙動になっていないか
  • 読み上げさせてはいけない箇所が、読み上げ可能になっていないか(例えば、課金によって初めてアクセス可能な文言)

また、Android Studioのコードインスペクタを実行(メニューバーのAnalyze -> Inspect Code...から実行できる)し、Android/Lint/Accessibilityの部分で指摘されていないかを確認すると良いでしょう。

タッチ領域の確保

タッチ領域の確保の部分で述べた、「レイアウト境界の表示」設定を有効にして、特にアイコン画像のみのボタンなど、タッチ領域が狭くなりがちなViewについてPadding等によって十分なサイズが確保されているかを確認すると良いです。

ユーザー補助検証ツール(Accessibility Scanner)でも、タッチ領域の狭いViewがないかの確認が可能です。指摘する領域サイズの閾値(最小サイズ)は、このツールの設定画面から変更が可能です。

フォントサイズの指定方法

以下手順で、Androidのシステム設定から「フォントサイズ」と「表示サイズ」を最大にし、レイアウトの表示崩れが発生していないかを確認するのが良いでしょう。

  1. 設定(Settings)アプリを開く
  2. ディスプレイ(Display)を選択する
  3. 詳細設定(Advanced)を選択する
  4. フォントサイズ(Font size) / 表示サイズ(Display size)を選択する
  5. スライダーを右端に寄せて、それぞれのサイズを最大にする

コントラスト比の確保

ユーザー補助検証ツール(Accessibility Scanner)を用いて検査すると良いです。指摘するコントラスト比の最小比率は、このツールの設定画面から変更が可能です。

おわりに

Androidアプリのアクセシビリティを向上させるために、考慮すべきこと、エンジニア側の視点でデザイナからどのようなインプットが必要なのか、適切に対応できたことをどのように確認するのか、について書きました。考えるべき項目が多く、大変かな、と思われた方もいるかもしれません。ですが、アプリを実装する前のデザイン・設計の段階でこれらを考慮しておけば、実装する際はそれほど手間をかけることなく対応できるものばかりだと思います。

あらゆる人がどのような環境でも利用でき、より多くの人たちに利用され、永く愛されるアプリにするために。ここまで読んでくださったあなたも、はじめてみませんか?


参考


  1. DroidKaigi 2020 - 残り15%のユーザーにリーチするためのAccessibility / coffeegyunyu [JA]にて例示されていました。

  2. Material DesignのAccessibility/Layout and typographyにて言及されています。

  3. ちなみに、iOSアプリを開発する際のガイドラインとなるHuman Interface GuidelinesAccessibility/Text Size and Weightでは、“As font size increases, avoid truncating text.”と記載があり、詳細画面のような別画面で全文を参照できる場合を除き、文言の省略を避け、スクロール操作によって全文読めるよう対応することが望ましい、とされています。

  4. Web Content Accessibility Guidelines。読んで字の如くWebコンテンツ向けのアクセシビリティガイドラインではあるが、スマートフォンアプリに対しても適用できるルールが多く、アクセシビリティを学ぶ際は必ず目を通すべきガイドラインです。