When the user gives focus to an editable text component, such as a`TextField`, and the device has a hardware keyboard attached, all input is handled by the system. You can provide keyboard shortcuts by handling key events.
| **Note:** Key events can be handled by implementing the[`KeyEvent.Callback`](https://developer.android.com/reference/android/view/KeyEvent.Callback)interface on an`Activity`class. Refer to[Handle keyboard actions](https://developer.android.com/develop/ui/views/touch-and-input/keyboard-input/commands)in views for details.

## Default keyboard shortcuts

The following keyboard shortcuts are available out of the box.

|                                                                    Keyboard shortcut                                                                     |                  Action                   |                Composables supporting the shortcut                 |
|----------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|--------------------------------------------------------------------|
| <kbd>Shift</kbd>+<kbd>Ctrl</kbd>+<kbd>Left arrow</kbd>/<kbd>Right arrow</kbd>                                                                            | Select text to beginning/end of word      | `BasicTextField`,`TextField`                                       |
| <kbd>Shift</kbd>+<kbd>Ctrl</kbd>+<kbd>Up arrow</kbd>/<kbd>Down arrow</kbd>                                                                               | Select text to beginning/end of paragraph | `BasicTextField`,`TextField`                                       |
| <kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>Up arrow</kbd>/<kbd>Down arrow</kbd>or<kbd>Shift</kbd>+<kbd>Meta</kbd>+<kbd>Left arrow</kbd>/<kbd>Right arrow</kbd> | Select text to beginning/end of text      | `BasicTextField`,`TextField`                                       |
| <kbd>Shift</kbd>+<kbd>Left arrow</kbd>/<kbd>Right arrow</kbd>                                                                                            | Select characters                         | `BasicTextField`,`TextField`                                       |
| <kbd>Ctrl</kbd>+<kbd>A</kbd>                                                                                                                             | Select all                                | `BasicTextField`,`TextField`                                       |
| <kbd>Ctrl</kbd>+<kbd>C</kbd>/<kbd>Ctrl</kbd>+<kbd>X</kbd>/<kbd>Ctrl</kbd>+<kbd>V</kbd>                                                                   | Copy/cut/paste                            | `BasicTextField`,`TextField`                                       |
| <kbd>Ctrl</kbd>+<kbd>Z</kbd>/<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd>                                                                               | Undo/redo                                 | `BasicTextField`,`TextField`                                       |
| <kbd>PageDown</kbd>/<kbd>PageUp</kbd>                                                                                                                    | Scroll                                    | `LazyColumn`, the`verticalScroll`modifier, the`scrollable`modifier |

| **Note:** The Meta key is not present on all keyboards. On macOS keyboards, the Meta key is the Command key; on Windows keyboards, the Windows key; and on ChromeOS keyboards, the Search key.

## Key events

In Compose, you can handle an individual keystroke with the[`onKeyEvent`](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/key/package-summary#(androidx.compose.ui.Modifier).onKeyEvent(kotlin.Function1))modifier. The modifier accepts a lambda that's called when the modified component receives a key event. A key event is described as a[`KeyEvent`](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/key/KeyEvent)object. You can get the information of each key event by referring to the object in the lambda passed to the`onKeyEvent`modifier.

A keystroke sends two key events. One is triggered when the user presses the key; the other is triggered when the key is released. You can distinguish the two key events by referring to the[`type`](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/key/KeyEvent#(androidx.compose.ui.input.key.KeyEvent).type())attribute of the`KeyEvent`object.

The return value of the`onKeyEvent`lambda indicates whether the key event is handled or not. Return`true`if your app handles the key event, which stops propagation of the event.

The following snippet shows how to call a`doSomething()`function when the user releases the<kbd>S</kbd>key on the`Box`component:  

    Box(
        modifier = Modifier.focusable().onKeyEvent {
            if(
                it.type == KeyEventType.KeyUp &&
                it.key == Key.S
            ) {
                doSomething()
                true
            } else {
                false
            }
        }
    )  {
        Text("Press S key")
    }

### Modifier keys

A`KeyEvent`object has the following attributes which indicate whether modifier keys are pressed or not:

- [`isAltPressed`](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/key/KeyEvent#(androidx.compose.ui.input.key.KeyEvent).isAltPressed())
- [`isCtrlPressed`](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/key/KeyEvent#(androidx.compose.ui.input.key.KeyEvent).isCtrlPressed())
- [`isMetaPressed`](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/key/KeyEvent#(androidx.compose.ui.input.key.KeyEvent).isMetaPressed())
- [`isShiftPressed`](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/key/KeyEvent#(androidx.compose.ui.input.key.KeyEvent).isShiftPressed()))

Be specific in describing the key events your app handles. The following snippet calls a`doSomething()`function only if the user releases just the<kbd>S</kbd>key. If the user presses any modifier key, such as the<kbd>Shift</kbd>key, the app does not call the function.  

    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")
    }

### Spacebar and Enter key click events

The<kbd>Spacebar</kbd>and<kbd>Enter</kbd>key trigger click events as well. For example, users can toggle (play or pause) media playback with the<kbd>Spacebar</kbd>or the<kbd>Enter</kbd>key by handling click events as follows:  

    MoviePlayer(
       modifier = Modifier.clickable { togglePausePlay() }
    )

The[`clickable`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/package-summary#(androidx.compose.ui.Modifier).clickable(kotlin.Boolean,kotlin.String,androidx.compose.ui.semantics.Role,kotlin.Function0))modifier intercepts key events and calls the`onClick()`callback when the<kbd>Spacebar</kbd>or<kbd>Enter</kbd>key is pressed. That's why the`togglePausePlay()`function is called by pressing the<kbd>Spacebar</kbd>or<kbd>Enter</kbd>key in the snippet.

### Unconsumed key events

Unconsumed key events are propagated from the component where the event occurred to the enclosing outer component. In the example below, the`InnerComponent`consumes key events when the<kbd>S</kbd>key is released, and so the`OuterComponent`does not receive any key events triggered by releasing the<kbd>S</kbd>key. That's why the`actionB()`function is never called.

Other key events on`InnerComponent`, such as releasing the<kbd>D</kbd>key, can be handled by the`OuterComponent`. The`actionC()`function is called because the key event for releasing the<kbd>D</kbd>key is propagated to the`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`modifier

In some use cases, you want to intercept a key event before it triggers the default action. Adding custom shortcuts to a`TextField`is a typical one. The following snippet enables users to move to the next focusable component by pressing the<kbd>tab</kbd>key.  

    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
            }
        }
    )

By default, the`TextField`component adds a tab character every time users press the<kbd>Tab</kbd>key, even if the key event is handled with the`onKeyEvent`modifier. To move the keyboard focus without adding any tab characters, handle the key event before triggering the actions associated with the key event, as in the snippet. The[`onKeyPreviewEvent()`](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/key/package-summary#(androidx.compose.ui.Modifier).onPreviewKeyEvent(kotlin.Function1))lambda intercepts the key event by returning`true`.

The parent component can intercept the key event happening on its children. In the following snippet, the`previewSKey()`function is called when users press the<kbd>S</kbd>key, instead of calling the`actionForPreview()`function.  

    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")
      }
    }

The`onPreviewKeyEvent()`lambda for the`Box`component is not triggered when users press the<kbd>Tab</kbd>key either. The`onPreviewKeyEvent()`lambda is called on the parent component first, then`onPreviewKeyEvent()`in the child component is called. You can implement screen-wide keyboard shortcuts by utilizing this behavior.

## Additional resources

- [Keyboard Shortcuts Helper](https://developer.android.com/develop/ui/compose/touch-input/keyboard-input/keyboard-shortcuts-helper): System screen that enables users to search for the keyboard shortcuts your app offers.