大画面のデバイスでは、キーボード、マウス、トラックパッド、タッチペン、ゲームパッドを使用してアプリを操作することが多くなります。アプリが外部デバイスからの入力を受け入れるようにするには、以下を行います。
- 基本的なキーボード サポートをテストする (元に戻すの Ctrl+Z、コピーの Ctrl+C、保存の Ctrl+S など)。デフォルトのキーボード ショートカットの一覧については、 キーボード アクションの処理をご覧ください。
- 高度なキーボード サポートをテストする (Tab キーと 矢印キーによるキーボード ナビゲーション、Enter キーによるテキスト入力の確定、 メディアアプリでの Spacebar による再生と一時停止など)。
- 基本的なマウス操作をテストする(右クリックしてコンテキスト メニューを表示する、 ユーザーがカーソルを合わせたときにアイコンを変更する、マウスホイールまたはトラックパッドでカスタム コンポーネントをスクロールするなど)。
- アプリ固有の入力デバイスをテストする (タッチペン、ゲーム コントローラ、音楽アプリの MIDI コントローラなど)。
- 高度な入力のサポートを検討する (パソコン環境でアプリの魅力を高めたい場合。DJ アプリ用のクロスフェーダーとしてのタッチパッド、ゲーム用のマウス キャプチャ、キーボードを多用するユーザー向けのキーボード ショートカットなど)。
キーボード
キーボード入力に対してアプリがどのように応答するかは、大画面でのユーザー エクスペリエンスを高める鍵になります。キーボード入力には、ナビゲーション、 キーストローク、ショートカットの 3 種類があります。
ナビゲーション
タップ中心のアプリにキーボード ナビゲーションが実装されることはまれですが、ユーザーはアプリの使用時にキーボードがあれば、キーボード ナビゲーションを期待します。ユーザー補助機能を必要とするユーザーにとっては、スマートフォン、タブレット、折りたたみ式デバイス、パソコンでキーボード ナビゲーションが不可欠となる場合があります。
多くのアプリでは、矢印キーと Tab キーによるナビゲーションは Android フレームワークによって自動的に処理されます。たとえば、Button はデフォルトでフォーカス可能であり、キーボード ナビゲーションは一般的に追加のコードなしで機能します。デフォルトではフォーカス可能でないビューのキーボード ナビゲーションを有効にするには、ビューをフォーカス可能としてマークします。これはプログラムまたは XML で実施できます。
Kotlin
yourView.isFocusable = true
Java
yourView.setFocusable(true);
代替策として、レイアウト ファイルで focusable 属性を設定する方法もあります。
android:focusable="true"
詳しくは、フォーカス処理をご覧ください。
フォーカスが有効になると、Android フレームワークはすべてのフォーカス可能なビューのナビゲーション マッピングを、位置に基づいて作成します。通常、これは想定どおりに機能し、特別な開発は不要です。デフォルト マッピングがアプリのニーズに合わない場合は、次のようにしてオーバーライドできます。
Kotlin
// Arrow keys
yourView.nextFocusLeftId = R.id.view_to_left
yourView.nextFocusRightId = R.id.view_to_right
yourView.nextFocusTopId = R.id.view_above
yourView.nextFocusBottomId = R.id.view_below
// Tab key
yourView.nextFocusForwardId = R.id.next_view
Java
// Arrow keys
yourView.setNextFocusLeftId(R.id.view_to_left);
yourView.setNextFocusRightId(R.id.view_to_left);
yourView.setNextFocusTopId(R.id.view_to_left);
yourView.setNextFocusBottomId(R.id.view_to_left);
// Tab key
yourView.setNextFocusForwardId(R.id.next_view);
キーボードのみを使用して、アプリのすべての UI 要素にアクセスできることをテストします。よく使用する要素には、マウス入力やタップ入力なしでアクセスできるようにする必要があります。
ユーザー補助機能を必要とするユーザーにとっては、キーボード サポートが不可欠であることに留意してください。
キーストローク
画面上の仮想キーボード(IME)によって処理されるテキスト入力の場合、
EditText
のようなアプリは、追加の開発作業がなくても大画面デバイスで想定どおりに動作します。フレームワークが予測できないキーストロークについては、アプリが独自に動作を処理する必要があります。これは、特にカスタムビューを使用するアプリに当てはまります。
例としては、Enter キーを使用してメッセージを送信するチャットアプリ、 Spacebar で再生の開始と停止を行うメディアアプリ、および w、a、s、および d キーで移動を制御するゲームなどがあります。
ほとんどのアプリは、onKeyUp() コールバックをオーバーライドし、受け取ったキーコードごとに期待される動作
を追加します。
Kotlin
kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
return when (keyCode) {
KeyEvent.KEYCODE_ENTER -> {
sendChatMessage()
true
}
KeyEvent.KEYCODE_SPACE -> {
playOrPauseMedia()
true
}
else -> super.onKeyUp(keyCode, event)
}
}
Java
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
sendMessage();
return true;
} else if (KeyEvent.KEYCODE_SPACE){
playOrPauseMedia();
return true;
} else {
return super.onKeyUp(keyCode, event);
}
}
An onKeyUp イベントは、キーが離されたときに発生します。このコールバックを使用すると、キーを長押ししたりゆっくり離したりした場合に、アプリが複数の onKeyDown イベントを処理する必要がなくなります。キーが押された瞬間を検出する必要があるか、ユーザーがキーを長押ししているかどうかを検出する必要があるゲームやアプリは、onKeyDown イベントをリッスンし、繰り返される onKeyDown イベントを独自に処理できます。
詳しくは、キーボード アクションの処理をご覧ください。
ショートカット
ハードウェア キーボードを使用する際は、Ctrl キー、Alt キー、 Shift キー、Meta キーを含む一般的なキーボード ショートカットが求められます。こうしたショートカットがアプリに実装されていないと、ユーザーがフラストレーションを感じる可能性があります。また上級ユーザーにとっては、よく使うアプリ固有のタスクのショートカットが役立ちます。ショートカットを実装することで、アプリの使いやすさを高め、ショートカットを備えていないアプリとの差別化を図ることができます。
一般的なショートカットには、Ctrl+S(保存)、Ctrl+Z (元に戻す)、Ctrl+Shift+Z(やり直し)などがあります。デフォルトのショートカットの一覧については、 キーボード アクションの処理をご覧ください。
ショートカットを有効にするには、dispatchKeyShortcutEvent() を
実装して、特定のキーコードのすべてのキーの組み合わせ(Alt、
Ctrl、Shift、Meta)をインターセプトします。
特定の修飾キーを確認するには、次を使用します。
KeyEvent.isCtrlPressed()、KeyEvent.isShiftPressed()、KeyEvent.isAltPressed()、KeyEvent.isMetaPressed()、または
Kotlin
override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean {
return when (event.keyCode) {
KeyEvent.KEYCODE_O -> {
openFile() // Ctrl+O, Shift+O, Alt+O
true
}
KeyEvent.KEYCODE_Z-> {
if (event.isCtrlPressed) {
if (event.isShiftPressed) {
redoLastAction() // Ctrl+Shift+Z pressed
true
} else {
undoLastAction() // Ctrl+Z pressed
true
}
}
}
else -> {
return super.dispatchKeyShortcutEvent(event)
}
}
}
Java
@Override
public boolean dispatchKeyShortcutEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_O) {
openFile(); // Ctrl+O, Shift+O, Alt+O
return true;
} else if(event.getKeyCode() == KeyEvent.KEYCODE_Z) {
if (event.isCtrlPressed()) {
if (event.isShiftPressed()) {
redoLastAction();
return true;
}
else {
undoLastAction();
return true;
}
}
}
return super.dispatchKeyShortcutEvent(event);
}
ショートカット コードを他のキーストローク処理(onKeyUp() や onKeyDown())から分離すると、すべての場合に手動で修飾キーのチェックを実装しなくても、修飾キーがデフォルトで受け入れられます。また、さまざまなキーボード レイアウトとオペレーティング システムに慣れたユーザーにとっては、あらゆる修飾キーの組み合わせが可能であれば、使いやすさが向上します。
ただし、KeyEvent.isCtrlPressed()、KeyEvent.isShiftPressed()、KeyEvent.isAltPressed() をチェックして、onKeyUp() でショートカットを実装することもできます。この方法では、変更されたキーの動作がショートカットというよりもアプリの動作の変更である場合に、メンテナンスが簡単になります。たとえば、
ゲームで W が「前に歩く」を意味し、Shift+W が「前に走る
」を意味する場合などです。
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
return when(keyCode) {
KeyEvent.KEYCODE_W-> {
if (event.isShiftPressed) {
if (event.isCtrlPressed) {
flyForward() // Ctrl+Shift+W pressed
true
} else {
runForward() // Shift+W pressed
true
}
} else {
walkForward() // W pressed
true
}
}
else -> super.onKeyUp(keyCode, event)
}
}
Java
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_W) {
if (event.isShiftPressed()) {
if (event.isCtrlPressed()) {
flyForward(); // Ctrl+Shift+W pressed
return true;
} else {
runForward(); // Shift+W pressed
return true;
}
} else {
walkForward();
return true;
}
}
return super.onKeyUp(keyCode, event);
}
キーボード ショートカット ヘルパーもご覧ください。
タッチペン
多くの大画面デバイスにはタッチペンが付属しています。Android アプリはタッチペンをタッチスクリーン入力として処理します。Wacom Intuos のように、USB または Bluetooth の描画 テーブルを備えたデバイスもあります。Android アプリは Bluetooth 入力は受け取れますが、USB 入力は受け取れません。
タッチペン イベントは、View#onTouchEvent()
または View#onGenericMotionEvent() によってタッチスクリーン イベントとして報告され、
MotionEvent#getSource() タイプの SOURCE_STYLUS を含みます。
MotionEvent オブジェクトには、イベントに関する情報が格納されます。
MotionEvent#getToolType()は、ディスプレイに触れたツールに応じてTOOL_TYPE_FINGER、TOOL_TYPE_STYLUS、またはTOOL_TYPE_ERASERを返します。MotionEvent#getPressure()はタッチペンに加えられた物理的な圧力をレポートします(サポートされている場合)。MotionEvent#getAxisValue()とMotionEvent.AXIS_TILTおよびMotionEvent.AXIS_ORIENTATIONを使用した は、タッチペンの物理的な傾きと向きを提供します (サポートされている場合)。
履歴ポイント
Android は、入力イベントを一括でまとめてフレームごとに 1 回送信します。タッチペン入力では、ディスプレイよりもはるかに高い頻度でイベントが報告される可能性があります。描画アプリを作成する場合は、getHistorical API を使用して、最近発生した可能性があるイベントをチェックします。
MotionEvent#getHistoricalX()MotionEvent#getHistoricalY()MotionEvent#getHistoricalPressure()MotionEvent#getHistoricalAxisValue()
パーム リジェクション
ユーザーがタッチペンを使用して描画、書き込み、またはアプリの操作を行うと、手のひらが画面に触れることがあります。タッチイベント(
ACTION_DOWN または ACTION_POINTER_DOWN に設定)が、システムに認識される前にアプリに報告される場合、手のひらでの意図しないタッチは無視されます。
Android は、MotionEvent をディスパッチすることにより、手のひらでのタッチイベントをキャンセルします。アプリが
ACTION_CANCELを受け取った場合、操作はキャンセルされます。アプリが
ACTION_POINTER_UPを受け取った場合は、FLAG_CANCELEDが設定されているかどうかを確認します。設定されている場合は、操作をキャンセルします。
FLAG_CANCELED のみの確認はしないでください。Android 13(API レベル 33)以降では、ACTION_CANCEL イベントに FLAG_CANCELED が設定されますが、Android の古いバージョンでは設定されません。
Android 12
Android 12(API レベル 32)以前の場合、パーム リジェクションの検出は、シングル ポインタ タッチイベントでのみ可能です。手のひらでのタッチが唯一のポインタである場合は、モーション イベント オブジェクトに ACTION_CANCEL が設定され、イベントはキャンセルされます。他のポインタがダウンしている場合、システムは ACTION_POINTER_UP を設定しますが、パーム リジェクション検出には不十分です。
Android 13
Android 13(API レベル 33)以降では、手のひらでのタッチが唯一のポインタである場合、モーション イベント オブジェクトに ACTION_CANCEL と FLAG_CANCELED が設定され、イベントがキャンセルされます。他のポインタがダウンしている場合、ACTION_POINTER_UP と FLAG_CANCELED が設定されます。
アプリが ACTION_POINTER_UP でモーション イベントを受け取った場合は必ず FLAG_CANCELED をチェックして、イベントがパーム リジェクション(または他のイベントのキャンセル)を示しているかどうかを確認します。
メモ作成アプリ
ChromeOS には、登録されたメモ作成アプリをユーザーに表示するための特別なインテントがあります。アプリをメモ作成アプリとして登録するには、アプリ マニフェストに次の行を追加します。
<intent-filter>
<action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
アプリがシステムに登録されると、ユーザーはそのアプリをデフォルトのメモ作成アプリとして選択できます。新しいメモがリクエストされた場合、アプリはタッチペン入力が可能な空のメモを作成する必要があります。ユーザーが画像(スクリーンショットやダウンロードした画像など)にアノテーションを付けようとした場合、アプリは content:// URI を持つアイテムを 1 つ以上含む ClipData とともに起動します。アプリは、最初の添付画像を背景画像として使用するメモを作成し、ユーザーがタッチペンで画面に描画できるモードに移行する必要があります。
タッチペンなしでメモ作成インテントをテストする
アプリがメモ作成インテントに正しく応答するかどうかを、アクティブなタッチペンがない状態でテストするには、次の方法で ChromeOS のメモ作成オプションを表示します。
- デベロッパー モードに切り替えて、デバイスを書き込み可能にする
- Ctrl+Alt+F2 キーを押して、ターミナルを開く
- コマンド
sudo vi /etc/chrome_dev.confを実行する iを押して入力モードに切り替え、ファイルの末尾に新しい行として--ash-enable-paletteを追加する- Esc キーを押してから :、w、 q を入力し、Enter キーを押して保存する
- Ctrl+Alt+F1 キーを押して、通常の ChromeOS UI に戻る
- ログアウトしてからログインし直す
これで、シェルフにタッチペン メニューが表示されるようになります。
- シェルフ内のタッチペン ボタンをタップし、[新しいメモ] を選択します。これにより、空白の描画メモが開きます。
- スクリーンショットを撮ります。シェルフからタッチペン ボタン > [画面をキャプチャ] を選択するか、画像をダウンロードします。画像にアノテーションを付ける オプションが通知に表示されます。これにより、画像にアノテーションを付けられる状態でアプリが起動します。
マウスとタッチパッドのサポート
一般的にほとんどのアプリは、右クリック、マウスオーバー、ドラッグ&ドロップという 3 つの大画面中心のイベントを処理するだけで済みます。 右クリック、マウスオーバー、ドラッグ& ドロップ。
右クリック
リストアイテムの長押しなど、アプリにコンテキスト メニューを表示させるためのアクションはすべて、右クリック イベントにも反応する必要があります。
右クリック イベントを処理するには、アプリで
View.OnContextClickListenerを登録する必要があります。
Kotlin
yourView.setOnContextClickListener {
showContextMenu()
true
}
Java
yourView.setOnContextClickListener(v -> {
showContextMenu();
return true;
});
コンテキスト メニューの作成の詳細については、コンテキスト メニューを作成するをご覧ください。
カーソルを合わせる
マウスオーバー イベントを適切に処理することで、アプリのレイアウトが洗練されていて使いやすいとユーザーに感じさせることができます。これは、カスタム ビュー:
Kotlin
// Change the icon to a "hand" pointer on hover.
// Highlight the view by changing the background.
yourView.setOnHoverListener { view, _ ->
addVisualHighlighting(true)
view.pointerIcon =
PointerIcon.getSystemIcon(view.context, PointerIcon.TYPE_HAND)
true // Listener consumes the event.
}
Java
// Change the icon to a "hand" pointer on hover.
// Highlight the view by changing the background.
yourView.setOnHoverListener((view, event) -> {
addVisualHighlighting(true);
view.setPointerIcon(
PointerIcon.getSystemIcon(view.getContext(), PointerIcon.TYPE_HAND)
);
return true; // Listener consumes the event.
});
最も一般的な例は次の 2 つです。
- マウスポインタ アイコンを変更することで、要素にインタラクティブな動作がある(たとえば、クリック可能または編集可能である)ことをユーザーに知らせる
- 大規模なリストまたはグリッド内のアイテムにポインタがカーソルを合わせたとき、そのアイテムに視覚的なフィードバックを追加する
ドラッグ&ドロップ
マルチウィンドウ環境では、ユーザーはアプリ間でアイテムをドラッグ&ドロップできることを期待します。これは、デスクトップ デバイス、タブレット、スマートフォン、分割画面モードの折りたたみ式デバイスに当てはまります。
ユーザーがアプリにアイテムをドラッグする可能性があるかどうかを考慮します。たとえば、写真エディタによる写真の受け取り、オーディオ プレーヤーによる音声ファイルの受け取り、描画プログラムによる写真の受け取りなどがあります。
ドラッグ&ドロップのサポートを追加するには、 ドラッグ&ドロップを有効にする をご覧ください。Android on ChromeOS — Implementing Drag & Drop のブログ投稿もご覧ください。
ChromeOS 向けの特別な考慮事項
- アプリ外からドラッグしたアイテムにアクセスするには、
requestDragAndDropPermissions()を使用して 権限をリクエストします。 他のアプリにアイテムをドラッグするには、アイテムに
View.DRAG_FLAG_GLOBALフラグを設定する必要があります。
高度なポインタのサポート
マウス入力とタッチパッド入力の高度な処理を行うアプリは、
View#onGenericMotionEvent() を実装し、[MotionEvent.getSource()][] を使用して
SOURCE_MOUSE と SOURCE_TOUCHSCREEN を区別します。
MotionEvent を調べて、次のような必要な動作を実装します。
- 移動によって
ACTION_HOVER_MOVEイベントを生成する。 - ボタンによって
ACTION_BUTTON_PRESSイベントとACTION_BUTTON_RELEASEイベントを生成する。 `getButtonState()` を使用して、すべてのマウスまたはトラックパッド ボタンの現在の状態をチェックすることもできる。 - マウスホイールのスクロールによって
ACTION_SCROLLイベントを生成する。
ゲーム コントローラ
大画面の Android デバイスの中には、最大 4 つのゲーム コントローラをサポートするものもあります。標準の Android ゲーム コントローラ API を使用してゲーム コントローラを処理します(ゲーム コントローラをサポートするをご覧ください)。
ゲーム コントローラのボタンは、一般的なマッピングに従って一般的な値にマッピングされます。 ただし、すべてのゲーム コントローラ メーカーが同じマッピング規則に従っているわけではありません。 各種の一般的なコントローラ マッピングをユーザーが選択できるようにすると、エクスペリエンスを大幅に向上させることができます。詳しくは、ゲームパッド ボタンの押下を処理するをご覧ください。
入力変換モード
ChromeOS では、デフォルトで入力変換モードが有効になっています。ほとんどの Android アプリの場合、このモードはパソコン環境で想定されるとおりに動作します。たとえば、タッチパッドでの 2 本指スクロール、マウスホイールによるスクロール、未加工のディスプレイ座標のウィンドウ座標へのマッピングなどが自動的に有効になります。 通常、アプリ デベロッパーはこうした動作を実装する必要はありません。
カスタムの入力動作をアプリに実装する(たとえば 2 本の指でタッチパッドをつまむカスタム操作を定義する)場合や、アプリが想定する入力イベントが入力変換によって提供されない場合は、Android マニフェストに次のタグを追加することにより、入力変換モードを無効にできます。
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />