ユーザーが編集可能なテキスト コンポーネント(TextField
など)にフォーカスを合わせると、
デバイスにハードウェア キーボードが接続されている
すべての入力がシステムによって処理されます。
キーイベントを処理することで、キーボード ショートカットを提供できます。
デフォルトのキーボード ショートカット
次のキーボード ショートカットは、すぐに使用できます。
キーボード ショートカット | アクション | ショートカットをサポートするコンポーザブル |
---|---|---|
Shift+Ctrl+左矢印/右矢印 | 単語の先頭/末尾までのテキストを選択する | BasicTextField 、TextField |
Shift+Ctrl+↑/↓ | 段落の先頭 / 末尾までのテキストを選択する | BasicTextField 、TextField |
Shift+Alt+上矢印 / 下矢印、または Shift+Meta+左矢印 / 右矢印 | テキストの先頭/末尾までのテキストを選択する | BasicTextField 、TextField |
Shift+←/→ | 文字を選択する | BasicTextField 、TextField |
Ctrl+A | すべて選択 | BasicTextField 、TextField |
Ctrl+C/Ctrl+X/Ctrl+V | コピー/切り取り/貼り付け | BasicTextField 、TextField |
Ctrl+Z/Ctrl+Shift+Z | 元に戻す/やり直す | BasicTextField 、TextField |
PageDown / PageUp | スクロール | LazyColumn 、verticalScroll 修飾子、scrollable 修飾子 |
重要なイベント
Compose では、個別のキー入力を処理できます。
onKeyEvent
修飾子
この修飾子は、変更されたコンポーネントがキーイベントを受信したときに呼び出されるラムダを受け取ります。キーイベントは KeyEvent
オブジェクトとして記述されます。各キーイベントの情報を取得するには、onKeyEvent
修飾子に渡されたラムダ内のオブジェクトを参照します。
キー入力は 2 つのキーイベントを送信します。1 つはユーザーがキーを押すとトリガーされます。
もう一方はキーが離されるとトリガーされます
この 2 つのキーイベントは、
KeyEvent
オブジェクトの type
属性を参照します。
onKeyEvent
ラムダの戻り値は、
キーイベントが処理されるかどうかに関係なく、
アプリがキーイベントを処理する場合は true
を返します。これにより、イベントの伝播が停止します。
次のスニペットは、doSomething()
関数を呼び出す方法を示しています。
ユーザーが Box
コンポーネントの S キーを放すと、次のようになります。
Box(
modifier = Modifier.focusable().onKeyEvent {
if(
it.type == KeyEventType.KeyUp &&
it.key == Key.S
) {
doSomething()
true
} else {
false
}
}
) {
Text("Press S key")
}
修飾キー
KeyEvent
オブジェクトには、次の属性があります。
修飾キーが押されたかどうかに関係なく:
アプリが処理するキーイベントを具体的に記述します。
次のスニペットは doSomething()
関数を呼び出します。
ユーザーが S キーのみを離したときのみ表示されます。
ユーザーが Shift キーなどの修飾子キーを押しても、アプリは関数を呼び出しません。
Box(
modifier = Modifier.focusable().onKeyEvent{
if(
it.type == KeyEventType.KeyUp &&
it.key == Key.S &&
!it.isAltPressed &&
!it.isCtrlPressed &&
!it.isMetaPressed &&
!it.isShiftPressed
) {
doSomething()
true
} else {
false
}
}
) {
Text("Press S key with a modifier key")
}
Space キーと Enter キーのクリック イベント
Space キーと Enter キーもクリック イベントをトリガーします。たとえば、メディアの再生を切り替える(再生または一時停止する)ことができます。 Space キーまたは Enter キー 次のようにクリック イベントを処理します。
MoviePlayer(
modifier = Modifier.clickable { togglePausePlay() }
)
clickable
修飾子がキーイベントをインターセプトする
スペースキーまたはキーが押されると onClick()
コールバックを呼び出します。
Enter キーを押す。
そのため、スニペットで Space キーまたは Enter キーを押すと、togglePausePlay()
関数が呼び出されます。
消費されていないキーイベント
未使用のキーイベントがコンポーネントから伝播される
外側のコンポーネントでイベントが発生した場所を示します。
次の例では、InnerComponent
は S キーがリリースされたときにキーイベントを消費するため、OuterComponent
は S キーのリリースによってトリガーされたキーイベントを受信しません。そのため、actionB()
関数は呼び出されません。
InnerComponent
の他のキーイベント(D キーのリリースなど)は、OuterComponent
で処理できます。actionC()
関数が呼び出されるのには、D キーを離すためのキーイベントが OuterComponent
に伝播されるためです。
OuterComponent(
modifier = Modifier.onKeyEvent {
when {
it.type == KeyEventType.KeyUp && it.key == Key.S -> {
actionB() // This function is never called.
true
}
it.type == KeyEventType.KeyUp && it.key == Key.D -> {
actionC()
true
}
else -> false
}
}
) {
InnerComponent(
modifier = Modifier.onKeyEvent {
if(it.type == KeyEventType.KeyUp && it.key == Key.S) {
actionA()
true
} else {
false
}
}
)
}
onKeyPreviewEvent
修飾子
ユースケースによっては、デフォルトのアクションをトリガーする前にキーイベントをインターセプトする必要があります。TextField
にカスタム ショートカットを追加するのは、典型的な方法です。
次のスニペットでは、ユーザーが Tab キーを押して、フォーカス可能な次のコンポーネントに移動できるようにします。
val focusManager = LocalFocusManager.current
var textFieldValue by remember { mutableStateOf(TextFieldValue()) }
TextField(
textFieldValue,
onValueChange = {
textFieldValue = it
},
modifier = Modifier.onPreviewKeyEvent {
if (it.type == KeyEventType.KeyUp && it.key == Key.Tab) {
focusManager.moveFocus(FocusDirection.Next)
true
} else {
false
}
}
)
デフォルトでは、TextField
コンポーネントは、キーイベントが onKeyEvent
修飾子で処理されている場合でも、ユーザーが Tab キーを押すたびにタブ文字を追加します。Tab 文字を追加せずにキーボードのフォーカスを移動するには、スニペットのように、キーイベントに関連付けられたアクションをトリガーする前にキーイベントを処理します。onKeyPreviewEvent()
ラムダは、true
を返すことでキーイベントをインターセプトします。
親コンポーネントは、その子で発生するキーイベントをインターセプトできます。
次のスニペットでは、ユーザーが S キーを押すと、actionForPreview()
関数ではなく previewSKey()
関数が呼び出されます。
Column(
modifier = Modifier.onPreviewKeyEvent{
if(it.key == Key.S){
previewSKey()
true
}else{
false
}
}
) {
Box(
modifier = Modifier
.focusable()
.onPreviewKeyEvent {
actionForPreview(it)
false
}
.onKeyEvent {
actionForKeyEvent(it)
true
}
) {
Text("Press any key")
}
}
ユーザーが Tab キーを押しても、Box
コンポーネントの onPreviewKeyEvent()
ラムダはトリガーされません。onPreviewKeyEvent()
ラムダは、まず親コンポーネントで呼び出され、次に子コンポーネントの onPreviewKeyEvent()
が呼び出されます。この動作を利用して、画面全体のキーボード ショートカットを実装できます。
参考情報
- キーボード ショートカット ヘルパー: 操作できるシステム画面 アプリが提供するキーボード ショートカットをユーザーが検索できます。