Android TV でのカスタムビューのユーザー補助サポート

多くの Android TV アプリはネイティブの Android コンポーネントで構築されていますが、特に カスタムビューを使用する場合は、サードパーティのフレームワークやコンポーネントのユーザー補助機能も考慮することが 重要です。

OpenGL または Canvas と直接やり取りするカスタムビュー コンポーネントは、Talkback やスイッチ アクセスなどのユーザー補助サービスとうまく連携できない場合があります。

Talkback をオンにした場合に発生する可能性のある問題について、以下にいくつか示します。

  • アプリでユーザー補助フォーカス(緑色の長方形)が表示されなくなることがあります。
  • ユーザー補助フォーカスが画面全体の境界を選択することがあります。
  • ユーザー補助フォーカスを移動できないことがあります。
  • コードで処理していても、D-pad の 4 方向キーが機能しないことがあります。

アプリでこれらの問題が発生した場合は、アプリが AccessibilityNodeInfo ツリーをユーザー補助サービスに公開していることを確認してください。

このガイドの残りの部分では、これらの問題に対処するための解決策とベスト プラクティスについて説明します。

D-pad イベントがユーザー補助サービスによって使用される

この問題の根本的な原因は、キーイベントがユーザー補助サービスによって使用されることです。

Dpad イベントの消費と Talkback
図 1.Talkback のオンとオフでシステムがどのように機能するかを示す図。

図 1 に示すように、Talkback がオンの場合、D-pad イベントはデベロッパーが定義した D-pad ハンドラに渡されません。代わりに、ユーザー補助サービスがキーイベントを受信して、ユーザー補助フォーカスを移動できるようにします。 カスタム Android コンポーネントは、画面上の位置に関する情報をデフォルトでユーザー補助サービスに公開しないため、ユーザー補助サービスはユーザー補助フォーカスを移動してハイライト表示することができません。

他のユーザー補助サービスも同様に影響を受けます。スイッチ アクセスを使用している場合も、D-pad イベントが使用されることがあります。

D-pad イベントはユーザー補助サービスに送信されますが、そのサービスはカスタムビュー内の UI コンポーネントの位置を認識していません。そのため、キーイベントを正しく転送するには、アプリに AccessibilityNodeInfo を実装する必要があります。

ユーザー補助サービスに情報を公開する

カスタムビューの位置 と説明に関する十分な情報をユーザー補助サービスに提供するには、AccessibilityNodeInfo を実装して、 各コンポーネントの詳細を公開します。ユーザー補助サービスがフォーカスを管理できるようにビューの論理的な関係を定義するには、 ExploreByTouchHelper を実装し、カスタムビューに ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat) を使用して設定します。

ExploreByTouchHelper を実装する場合は、次の 4 つの抽象メソッドをオーバーライドします。

Kotlin

// Return the virtual view ID whose view is covered by the input point (x, y).
protected fun getVirtualViewAt(x: Float, y: Float): Int

// Fill the virtual view ID list into the input parameter virtualViewIds.
protected fun getVisibleVirtualViews(virtualViewIds: List<Int>)

// For the view whose virtualViewId is the input virtualViewId, populate the
// accessibility node information into the AccessibilityNodeInfoCompat parameter.
protected fun onPopulateNodeForVirtualView(virtualViewId: Int, @NonNull node: AccessibilityNodeInfoCompat)

// Set the accessibility handling when perform action.
protected fun onPerformActionForVirtualView(virtualViewId: Int, action: Int, @Nullable arguments: Bundle): Boolean

Java

// Return the virtual view ID whose view is covered by the input point (x, y).
protected int getVirtualViewAt(float x, float y)

// Fill the virtual view ID list into the input parameter virtualViewIds.
protected void getVisibleVirtualViews(List<Integer> virtualViewIds)

// For the view whose virtualViewId is the input virtualViewId, populate the
// accessibility node information into the AccessibilityNodeInfoCompat parameter.
protected void onPopulateNodeForVirtualView(int virtualViewId, @NonNull AccessibilityNodeInfoCompat node)

// Set the accessibility handling when perform action.
protected boolean onPerformActionForVirtualView(int virtualViewId, int action, @Nullable Bundle arguments)

詳細については、Google I/O 2013 - Enabling Blind and Low-Vision Accessibility on Android をご覧いただくか、ユーザー補助 イベントの入力についての記事をご覧ください。

ベスト プラクティス

サンプル

カスタムビューを使用するアプリにユーザー補助サポートを追加するためのベスト プラクティスについては、Android TV のカスタムビューのユーザー補助のサンプルをご覧ください。