1. はじめに
アプリが標準のスマートフォンで利用可能な場合、タブレット、折りたたみ式デバイス、ChromeOS デバイスなどの大画面デバイスでも利用できます。
ユーザーは小画面での UX と同等かそれ以上のユーザー エクスペリエンスを、アプリが大画面でも提供することを期待しています。
また、大画面デバイスの場合、ユーザーは物理キーボードやマウス、トラックパッドなどのポインティング デバイスでアプリを使用する可能性が高くなります。Chromebook などの一部の大画面デバイスには、物理キーボードとポインティング デバイスが搭載されています。それ以外のデバイスの場合は、USB または Bluetooth のキーボードとポインティング デバイスに接続します。ユーザーは物理キーボードとポインティング デバイスでアプリを使用しているときも、タッチ スクリーンでアプリを使用しているときと同じタスクを実行できることを求めています。
前提条件
- Compose を使ってアプリを構築した経験
- Kotlin に関する基本的な知識(ラムダやコルーチンなど)
構築内容
Jetpack Compose ベースのアプリに、物理キーボードとマウスのサポートを追加します。手順は次のとおりです。
- 大画面のアプリの品質に関するガイドラインで定義されている条件に基づきアプリを確認する
- 監査結果をレビューして、物理キーボードとマウスのサポートに関する問題を特定する
- 問題を修正する
具体的には、サンプルアプリを次の点でアップデートします。
- キーボードの操作
- 上下にスクロールするキーボード ショートカット
- キーボード ショートカット ヘルパー
学習内容
- 仮想デバイスのサポートに関してアプリを監査する方法
- Compose でキーボード ナビゲーションを管理する方法
- Compose でキーボード ショートカットを追加する方法
必要なもの
- Android Studio Hedgehog 以降
- サンプルアプリを実行する次のいずれかのデバイス:
- 物理キーボードとマウスを搭載した大画面デバイス
- プロファイルがデスクトップ デバイス定義カテゴリに属する Android 仮想デバイス
2. セットアップ
- large-screen-codelabs の GitHub リポジトリのクローンを作成します。
git clone https://github.com/android/large-screen-codelabs
または、large-screen-codelabs の ZIP ファイルをダウンロードしてアーカイブを解除します。
add-keyboard-and-mouse-support-with-compose
フォルダに移動します。- Android Studio でプロジェクトを開きます。
add-keyboard-and-cursor-support-with-compose
フォルダには 1 つのプロジェクトが含まれています。 - Android タブレット、折りたたみ式デバイス、物理キーボードとマウスを搭載した ChromeOS デバイスがない場合は、Android Studio でデバイス マネージャーを開き、[Desktop] カテゴリで仮想デバイスを作成します。
3. アプリを使ってみる
サンプルアプリには記事のリストが表示されます。ユーザーはリストから選択した記事を閲覧できます。
アプリはアプリのウィンドウ幅に応じてレイアウトを適宜更新します。アプリのウィンドウ幅を分類するウィンドウ クラスには、コンパクト、中程度、拡大の 3 つがあります。
コンパクトと中程度ウィンドウ サイズクラスのレイアウト
アプリはシングルペイン レイアウトを使用します。アプリのホーム画面に記事のリストが表示されます。ユーザーがリストから記事を選択すると、画面遷移が行われ、記事が表示されます。
グローバル ナビゲーションは、ナビゲーション ドロワーで実装されます。
拡大ウィンドウ サイズクラスのレイアウト
このアプリはリストと詳細レイアウトを使用します。リストペインには記事のリストが表示されます。詳細ペインには選択した記事が表示されます。
グローバル ナビゲーションは、ナビゲーション レールで実装されます。
4. 背景情報
Compose には、アプリが物理キーボードとマウスからのイベントを処理するうえで役立つ、さまざまな API が用意されています。一部の API では、タッチイベントの処理と同様のキーボード イベントとマウスイベントの処理が可能です。そのため、多くのユースケースで、デベロッパーによる開発の手間なく、アプリで物理キーボードとマウスをサポートできます。
典型的な例としては、クリックの検出を可能にする clickable
修飾子があります。指でのタップがクリックとして検出されます。マウスクリックと Enter
キーの押下もクリックとして検出されます。アプリが clickable
修飾子でクリックを検出すると、入力デバイスに関係なく、アプリはユーザーがコンポーネントを操作できるようにします。
ただ、このハイレベルな API のサポートがあるものの、それでも物理キーボードとマウスのサポートには開発作業が必要となります。その理由は、アプリをテストして特殊なケースを把握する必要があるためです。また、次のようなデバイスの特性により発生するユーザーの負担を軽減する必要もあります。
- ユーザーがクリックできるコンポーネントを特定できない
- ユーザーが思うようにキーボード フォーカスを動かせない
- ユーザーが物理キーボードを使用している場合上下にスクロールできない
キーボード フォーカス
キーボード フォーカスは、物理キーボードと画面タップのインタラクションにおける主な違いです。ユーザーは以前にタップしたコンポーネントの位置に関係なく、画面上の任意のコンポーネントをタップできます。一方、キーボードの場合、実際のインタラクションを開始する前に、操作するコンポーネントを選択する必要があります。この選択を「キーボード フォーカス」と呼びます。
ユーザーは Tab
キーと方向キー(または矢印キー)を使用してキーボード フォーカスを移動できます。キーボード フォーカスは、デフォルトでは隣接するコンポーネントにのみ移動します。
物理キーボードによる煩わしさのほとんどは、キーボードのフォーカスに関連しています。よくある問題としては次のものがあります。
- 操作するコンポーネントにキーボード フォーカスを移動できない
Enter
キーを押しても、コンポーネントがクリックを検知しない- キーボード フォーカスがユーザーの想定と異なる形で移動する
- 画面遷移後、操作するコンポーネントにキーボード フォーカスを移動するには、数多くのキーを押さなければならない
- キーボード フォーカスを示す目印がないため、どのコンポーネントにキーボード フォーカスがあるかを判断できない
- 新しい画面に移動したときに、キーボード フォーカスがあるデフォルト コンポーネントを判断できない
キーボード フォーカスを視覚的に示すことは重要です。視覚的に示していないと、ユーザーはアプリでフォーカスを見つけられず、Enter
キーを押したときに何が起こるかを把握できません。ハイライト表示は、キーボード フォーカスを示すうえでよく使われる視覚的な目印です。右側のカードにあるボタンにキーボード フォーカスがあることが、ハイライト表示されていることからわかります。
キーボード ショートカット
ユーザーは物理キーボードでアプリを使用しているときに、一般的なキーボード ショートカットを使用できることを求めています。一部のコンポーネントでは、デフォルトで標準のキーボード ショートカットが有効になっています。BasicTextField
がその典型的な例です。これにより、ユーザーは次のような標準のテキスト編集キーボード ショートカットを使用できます。
ショートカット | 機能 |
| コピー |
| 切り取り |
| 貼り付け |
| 元に戻す |
| やり直す |
アプリでキーボード ショートカットを追加するには、キーイベントを処理します。onKeyEvent
修飾子と onPreviewKeyEvent
修飾子を使用すると、キーイベントをモニタリングできます。
ポインティング デバイス: マウス、トラックパッド、タッチペン
アプリはマウス、トラックパッド、タッチペンを同じ方法で処理します。トラックパッドをタップすると、clickable
修飾子によりクリックとして検知されます。タッチペンでタップした場合も、クリックとして検知されます。
コンポーネントをクリックできるかどうかについて、ユーザーが視覚的に理解できるようにすることが重要です。そのため、大画面アプリの品質に関するガイドラインではホバー状態について言及しています。
マテリアル 3 コンポーネントはデフォルトでホバー状態をサポートしています。マテリアル 3 にはホバー状態の視覚効果が備わっています。indication
修飾子を使用して、インタラクティブ コンポーネントに適用できます。
スクロール
スクロール可能なコンテナは、デフォルトでマウスホイールによるスクロール、トラックパッドでのスクロール ジェスチャー、Page up
キーと Page down
キーによるスクロールをサポートしています。
水平スクロールでは、ホバー状態で左右の矢印ボタンを表示するようにすると、ユーザーがそのボタンをクリックしてコンテンツをスクロールできるため、アプリが非常にユーザー フレンドリーになります。
デバイスの接続と切断による構成の変更
ユーザーはアプリの実行中にキーボードとマウスを接続したり、切断したりすることがあります。大量のテキストを入力するテキスト フィールドが表示された場合、ユーザーは物理キーボードを接続することがあります。Bluetooth 接続のマウスはスリープモードになると、接続が切断されます。USB 接続のキーボードが誤って外れることもあります。
周辺機器のハードウェアの接続または切断は、構成の変更をトリガーします。アプリは構成の変更中ずっと、状態を保持する必要があります。詳細については、UI の状態を保存するをご覧ください。
5. キーボードとマウスでサンプルアプリを確認する
物理キーボードとマウスのサポートの開発作業を開始するには、サンプルアプリを起動して、次の点を確認します。
- ユーザーはキーボード フォーカスをすべてのインタラクティブ コンポーネントに移動できる
- ユーザーは
Enter
キーでフォーカスされたコンポーネントを「クリック」できる - インタラクティブ コンポーネントは、キーボード フォーカスになると、そのことを示す
Tab
キー、Shift+Tab
キー、方向(矢印)キーを使用して、キーボード フォーカスをユーザーの想定どおりに(確立された規則に沿って)移動できる- インタラクティブ コンポーネントにはホバー状態がある
- ユーザーはインタラクティブ コンポーネントをクリックできる
- コンテキスト メニューは長押しまたはテキスト選択でコンテキスト メニューが表示されるコンポーネントなど、適切なコンポーネントを右クリック(セカンダリ コントロール クリック)すると表示される
この Codelab では、すべてのアイテムを 2 回確認する必要があります。1 回はシングルペイン レイアウト用、もう 1 回はリストと詳細レイアウト用に確認します。
この Codelab で修正する問題
問題が見つかり、この Codelab で次の点を修正します。
- ユーザーは記事を下にスクロールできないため、物理キーボードのみでは記事全体を読めない
- ユーザーは詳細ペインにキーボード フォーカスがあるかどうかを判断できない
6. ユーザーが詳細ペインで記事全体を読めるようにする
詳細ペインには選択した記事が表示されます。記事によっては長すぎて、スクロールせずには記事全体を読めません。ただ、ユーザーは物理キーボードのみでは記事を上下にスクロールできません。
LazyColumn
などのスクロール可能なコンテナでは、ユーザーは Page down
キーで下にスクロールできます。この問題の根本原因は、ユーザーがキーボード フォーカスを詳細ペインに移動できないことにあります。
コンポーネントはキーボード イベントを受信できるように、キーボード フォーカスできる必要があります。focusable
修飾子を使用すると、変更されたコンポーネントがキーボード フォーカスされるようになります。
この問題を解決するには次の手順に沿って操作します。
ui/article/PostContent.kt
ファイルでコンポーズ可能な関数PostContent
にアクセスします。focusable
修飾子を使用してコンポーズ可能な関数LazyColumn
を変更します。
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
post: Post,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
state: LazyListState = rememberLazyListState(),
coroutineScope: CoroutineScope = rememberCoroutineScope(),
focusRequester: FocusRequester = remember { FocusRequester() },
header: (@Composable () -> Unit)? = null
) {
LazyColumn(
contentPadding = contentPadding,
modifier = modifier
.padding(horizontal = defaultSpacerSize)
.focusable(),
state = state,
) {
// Code to layout the selected article.
}
}
記事にキーボード フォーカスがあることを示す
これで、ユーザーは Page down
キーで記事を下にスクロールして、記事全体を読めるようになりました。しかし、視覚効果がないため、PostContent
コンポーネントにキーボード フォーカスがあるかどうかを判断するのは困難です。
Indication
をコンポーネントに関連付けることにより、アプリでキーボード フォーカスを視覚的に示せます。Indication はインタラクションに応じて視覚効果をレンダリングするオブジェクトを作成します。たとえば、マテリアル 3 のデフォルトの Indication では、キーボード フォーカスがあるコンポーネントがハイライト表示されます。
サンプルアプリには、BorderIndication
という Indication
があります。これにより、キーボード フォーカスがあるコンポーネントの横に線が表示されます(次のスクリーンショットをご参照ください)。コードは ui/components/BorderIndication.kt
ファイルに保存されます。
PostConent
コンポーザブルにキーボード フォーカスがあるときに BorderIndication
を表示するには、次の手順に沿って操作します。
ui/article/PostContent.kt
ファイルでコンポーズ可能な関数PostContent
にアクセスします。remember()
関数の戻り値に関連付けられたinteractionSource
値を宣言します。- 作成された
MutableInteractionSource
オブジェクトがinteractionSource
値に関連付けられるように、remember()
関数でMutableInteractionSource()
関数を呼び出します。 - interactionSource パラメータを使用して
interactionSource
値をfocusable
修飾子に渡します。 indication
修飾子の呼び出しの後にfocusable
修飾子を呼び出すように、PostContent
コンポーザブルの修飾子を変更します。interactionSource
値とBorderIndication
関数の戻り値を Indication 修飾子に渡します。
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
post: Post,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
state: LazyListState = rememberLazyListState(),
coroutineScope: CoroutineScope = rememberCoroutineScope(),
focusRequester: FocusRequester = remember { FocusRequester() },
header: (@Composable () -> Unit)? = null
) {
val interactionSource = remember { MutableInteractionSource() }
LazyColumn(
contentPadding = contentPadding,
modifier = modifier
.padding(horizontal = defaultSpacerSize)
.indication(interactionSource, BorderIndication())
.focusable(interactionSource = interactionSource),
state = state,
) {
// Code to layout the selected article.
}
}
上下にスクロールするキーボード ショートカットを追加する
ユーザーが Spacebar
を使って上下にスクロールできるようにすることは一般的な機能です。アプリでこの機能を実装するには、次の表に示すようにキーボード ショートカットを追加します。
ショートカット | 機能 |
| 記事を下にスクロール |
| 記事を上にスクロール |
onKeyEvent
修飾子を使用すると、アプリは変更されたコンポーネントで発生するキーイベントを処理できます。この修飾子は、キーイベントを記述する KeyEvent
オブジェクトで呼び出されるラムダを受け取ります。ラムダはキーイベントが使用されたかどうかを示す Boolean
値を返します。
LazyColumn
と LazyRow
のスクロール位置は LazyListState
オブジェクトでキャプチャされます。アプリは LazyListState
オブジェクトに対して animateScrollBy()
の suspend メソッドを呼び出すことで、スクロールをトリガーできます。このメソッドは LazyColumn
を指定されたピクセル数、下にスクロールします。負の浮動小数点値を指定して suspend 関数を呼び出すと、関数は LazyColumn
を上にスクロールします。
このようなキーボード ショートカットを実装するには、次の手順に沿って操作します。
ui/article/PostContent.kt
ファイルでコンポーズ可能な関数PostContent
にアクセスします。onKeyEvent
修飾子を使用してコンポーズ可能な関数LazyColumn
を変更します。- 次のように、
onKeyEvent
修飾子に渡されるラムダにif
式を追加します。
- 次の条件が満たされている場合、
true
を返す Spacebar
が押されている(type
属性がKeyType.KeyDown
で、key
属性がKey.Spacebar
であるかをテストすることで検出可能)isCtrlPressed
属性は false であるため、Ctrl
キーは押されていないisAltPressed
属性は false であるため、Alt
キーは押されていないisMetaPressed
属性は false であるため、Meta
キー(注を参照)は押されていない- それ以外の場合は
false
を返す
- 以下のようにして、
Spacebar
でスクロールの量を決定します。
Shift
キーが押されたときは-0.4f
で、これは所定のKeyEvent
オブジェクトのisShiftPressed
属性で記述される- それ以外の場合は
0.4f
- コンポーズ可能な関数
PostContent
のパラメータであるcoroutineScope
に対してlaunch()
メソッドを呼び出します。 - 先ほどのステップで算出した相対的なスクロール量と、
launch
メソッドのランダム パラメータのstate.layoutInfo.viewportSize.height
属性を乗算して、実際のスクロール量を計算します。この属性はコンポーズ可能な関数PostContent
で呼び出されるLazyColumn
の高さを表します。 launch()
メソッドのラムダでstate.animateScrollBy()
メソッドを呼び出して、垂直スクロールをトリガーします。
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
post: Post,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
state: LazyListState = rememberLazyListState(),
coroutineScope: CoroutineScope = rememberCoroutineScope(),
focusRequester: FocusRequester = remember { FocusRequester() },
header: (@Composable () -> Unit)? = null
) {
val interactionSource = remember { MutableInteractionSource() }
LazyColumn(
contentPadding = contentPadding,
modifier = modifier
.padding(horizontal = defaultSpacerSize)
.onKeyEvent {
if (
it.type == KeyEventType.KeyDown &&
it.key == Key.Spacebar &&
!it.isCtrlPressed &&
!it.isAltPressed &&
!it.isMetaPressed
) {
val relativeAmount = if (it.isShiftPressed) {
-0.4f
} else {
0.4f
}
coroutineScope.launch {
state.animateScrollBy(relativeAmount * state.layoutInfo.viewportSize.height)
}
true
} else {
false
}
}
.indication(interactionSource, BorderIndication())
.focusable(interactionSource = interactionSource),
state = state,
) {
// Code to layout the selected article.
}
}
キーボード ショートカットをユーザーに知らせる
ユーザーがショートカットについて知らなければ、追加されたキーボードを十分に活用できません。アプリでは、Android システム UI の一部であるキーボード ショートカット ヘルパーを使用して、利用できるショートカットをユーザーに共有できます。ユーザーは Meta+/
でショートカット ヘルパーを開けます。
アプリのメイン アクティビティで onProvideKeyboardShortcuts()
メソッドをオーバーライドして、キーボード ショートカット ヘルパーにキーボード ショートカットのリストを渡します。
具体的には、アプリは onProvideKeyboardShortcuts()
に渡される可変リストに KeyboardShortcutGroup
オブジェクトを追加することで、それらのオブジェクトを提供します。各 KeyboardShortcutGroup
はキーボード ショートカットの名前が付いたカテゴリを表しています。これにより、アプリは利用できるキーボード ショートカットを目的やコンテキスト別にグループ化できます。
サンプルアプリには、Spacebar
と Shift+Spacebar
の 2 つのキーボード ショートカットがあります。
キーボード ショートカット ヘルパーにこの 2 つのショートカットが表示されるようにするには、次の手順を行います。
MainActivity.kt
ファイルを開きます。MainActivity
のonProvideKeyboardShortcuts()
メソッドをオーバーライドします。- キーボード ショートカット ヘルパーを使用できるように、Android SDK のバージョンが Android 7.0(API レベル 24)以降であることを確認します。
- メソッドの最初のパラメータが
null
ではないことを確認します。 - 次のパラメータを使用して、
Spacebar
キーのKeyboardShortcutInfo
オブジェクトを作成します。
- 説明テキスト
android.view.KeyEvent.KEYCODE_SPACE
0
(修飾子がないことを示す)
- 次のパラメータを使用して、
Shift+Spacebar
の別のKeyboardShortcutInfo
を作成します。
- 説明テキスト
android.view.KeyEvent.KEYCODE_SPACE
android.view.KeyEvent.META_SHIFT_ON
- 2 つの
KeyboardShortcutInfo
オブジェクトを含む不変リストを作成します。 - 次のパラメータを使用して
KeyboardShortcutGroup
オブジェクトを作成します。
- グループ名(テキスト)
- 前のステップの不変リスト
onProvideKeyboardShortcuts()
メソッドの最初のパラメータとして渡される可変リストに、KeyboardShortcutGroup
オブジェクトを追加します。
オーバーライドされたメソッドは次のようになります。
override fun onProvideKeyboardShortcuts(
data: MutableList<KeyboardShortcutGroup>?,
menu: Menu?,
deviceId: Int
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && data != null) {
val shortcutGroup = KeyboardShortcutGroup(
"To read articles",
listOf(
KeyboardShortcutInfo("Scroll down", KeyEvent.KEYCODE_SPACE, 0), // 0 means no modifier key is pressed
KeyboardShortcutInfo("Scroll up", KeyEvent.KEYCODE_SPACE, KeyEvent.META_SHIFT_ON),
)
)
data.add(shortcutGroup)
}
}
実行する
これで、ユーザーは Spacebar
で記事をスクロールして、記事全体を読めるようになりました。スクロールできるかどうかを試すには、Tab
キーまたは方向キーを使用して、キーボード フォーカスを記事に移動させます。Spacebar
を押すよう促すメッセージが表示されます。
キーボード ショートカット ヘルパーに、追加した 2 つのキーボード ショートカットが表示されます(Meta+/
キーを押します)。追加したショートカットは [現在のアプリ] タブに表示されます。
7. 詳細ペインでのキーボード ナビゲーションを迅速化する
アプリが拡大ウィンドウ サイズクラスで実行されている場合、ユーザーは Tab
キーを数回押して、キーボード フォーカスを詳細ペインに移動する必要があります。右方向キーを使用すると、ユーザーは 1 回の操作でキーボード フォーカスを記事リストから記事に移動できますが、それでもキーボード フォーカスを移動する必要はあります。初期フォーカスは、記事を読むというユーザーの主な目的をサポートしていません。
アプリで FocusRequester
オブジェクトを使用することによって、特定のコンポーネントにキーボード フォーカスを移動するようリクエストできます。focusRequester
修飾子は、変更されたコンポーネントに FocusRequester
オブジェクトを関連付けます。アプリは FocusRequester
オブジェクトの requestFocus()
メソッドを呼び出すことにより、フォーカスを移動する実際のリクエストを送信できます。
キーボード フォーカスの移動リクエストの送信は、コンポーネントの副次的な結果です。アプリは LaunchedEffect
関数を使用して、適切な方法でメソッドを呼び出す必要があります。
ユーザーが記事リストから記事を選択したときに PostContent
コンポーザブルがキーボード フォーカス状態になるよう設定する手順は次のとおりです。
ui/article/
PostContent.kt
ファイルでコンポーズ可能な関数PostContent
にアクセスします。focusRequester
修飾子を使用して、focusRequester
値をコンポーズ可能な関数LazyColumn
に関連付けます。focusRequester 値はコンポーズ可能な関数PostContent
のオプション パラメータとして指定されます。- コンポーズ可能な関数
PostContent
の最初のパラメータであるpost
を指定してLaunchedEffect
を呼び出し、ユーザーが記事を選択したときに渡されたラムダが呼び出されるようにします。 LaunchedEffect
関数に渡されるラムダのfocusRequester.requestFocus()
メソッドを呼び出します。
更新された PostContent
コンポーザブルは次のようになります。
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostContent(
post: Post,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
state: LazyListState = rememberLazyListState(),
coroutineScope: CoroutineScope = rememberCoroutineScope(),
focusRequester: FocusRequester = remember { FocusRequester() },
header: (@Composable () -> Unit)? = null
) {
val interactionSource = remember { MutableInteractionSource() }
LaunchedEffect(post) {
focusRequester.requestFocus()
}
LazyColumn(
contentPadding = contentPadding,
modifier = modifier
.padding(horizontal = defaultSpacerSize)
.onKeyEvent {
if (it.type == KeyEventType.KeyDown && it.key == Key.Spacebar) {
val relativeAmount = if (it.isShiftPressed) {
-0.4f
} else {
0.4f
}
coroutineScope.launch {
state.animateScrollBy(relativeAmount * state.layoutInfo.viewportSize.height)
}
true
} else {
false
}
}
.focusRequester(focusRequester),
.indication(interactionSource, BorderIndication())
.focusable(interactionSource = interactionSource),
state = state,
) {
// Code to layout the selected article.
}
}
実行する
これでユーザーが記事リストから記事を選択すると、キーボード フォーカスが記事に移動するようになりました。記事を選択すると、Spacebar
を使用して記事を下にスクロールするよう促すメッセージが表示されます。
8. 完了
おめでとうございます。物理キーボードとマウスのサポートをサンプルアプリに追加できました。これにより、ユーザーは物理キーボードまたはマウスのみを使用して、記事リストから記事を選択し、選択した記事を読めるようになります。
物理キーボードとマウスのサポートを追加するうえで必要な次のことを学習しました。
- アプリが物理キーボードとマウスをサポートしているかどうかを確認する方法(エミュレータを使った場合を含む)
- Compose でキーボード ナビゲーションを管理する方法
- Compose でキーボード ショートカットを追加する方法
また、若干のコード変更を行って、物理キーボードとマウスのサポートを追加しました。
これで、Compose を使用して、製品版アプリに物理キーボードとマウスのサポートを追加できるようになりました。
もう少し学習することにより、次の機能のキーボード ショートカットを追加できるようになります。
- 選択した記事に高評価を付ける
- 選択した記事をブックマークする
- 選択した記事を他のアプリで共有する