Обработка действий с клавиатуры

Когда пользователь фокусирует внимание на редактируемом текстовом компоненте, таком как TextField , и к устройству подключена аппаратная клавиатура, весь ввод обрабатывается системой. Вы можете предоставить сочетания клавиш, обрабатывая ключевые события.

Сочетания клавиш по умолчанию

Следующие сочетания клавиш доступны по умолчанию.

Сочетание клавиш Действие Composables, поддерживающие ярлык
Shift + Ctrl + Стрелка влево / Стрелка вправо Выделить текст до начала/конца слова BasicTextField , TextField
Shift + Ctrl + Стрелка вверх / Стрелка вниз Выделить текст до начала/конца абзаца BasicTextField , TextField
Shift + Alt + Стрелка вверх / Стрелка вниз или Shift + Meta + Стрелка влево / Стрелка вправо Выделить текст до начала/конца текста BasicTextField , TextField
Shift + стрелка влево / стрелка вправо Выберите персонажей BasicTextField , TextField
Ctrl + А Выбрать все 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 .

Нажатие клавиши отправляет два ключевых события. Один срабатывает, когда пользователь нажимает клавишу; другой срабатывает при отпускании ключа. Вы можете отличить два ключевых события, обратившись к атрибуту type объекта KeyEvent .

Возвращаемое значение лямбды onKeyEvent указывает, обработано ли событие ключа или нет. Возвращайте true если ваше приложение обрабатывает ключевое событие, которое останавливает распространение события.

В следующем фрагменте показано, как вызвать функцию doSomething() , когда пользователь отпускает клавишу S в компоненте Box :

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

События нажатия клавиши «Пробел» и «Ввод»

Клавиша «Пробел» и «Ввод» также запускают события щелчка. Например, пользователи могут переключать (воспроизводить или приостанавливать) воспроизведение мультимедиа с помощью клавиши пробела или клавиши Enter , обрабатывая события щелчка следующим образом:

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

Модификатор clickable перехватывает события нажатия клавиш и вызывает обратный вызов onClick() при нажатии клавиши пробела или клавиши Enter . Вот почему функция togglePausePlay() вызывается нажатием клавиши пробела или Enter во фрагменте.

Неиспользованные ключевые события

Неиспользованные ключевые события передаются из компонента, в котором произошло событие, во вмещающий внешний компонент. В приведенном ниже примере 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 является типичным. Следующий фрагмент позволяет пользователям перейти к следующему фокусируемому компоненту, нажав клавишу табуляции .

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 добавляет символ табуляции каждый раз, когда пользователи нажимают клавишу Tab , даже если событие нажатия клавиши обрабатывается с помощью модификатора onKeyEvent . Чтобы переместить фокус клавиатуры без добавления символов табуляции, обработайте событие клавиши перед запуском действий, связанных с событием клавиши, как во фрагменте. Лямбда onKeyPreviewEvent() перехватывает событие ключа, возвращая true .

Родительский компонент может перехватить ключевое событие, происходящее на его дочерних компонентах. В следующем фрагменте кода функцияпредварительного previewSKey() вызывается, когда пользователи нажимают клавишу S , вместо вызова функции actionForPreview() .

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

Лямбда-выражение onPreviewKeyEvent() для компонента Box также не срабатывает, когда пользователи нажимают клавишу Tab . Лямбда onPreviewKeyEvent() сначала вызывается в родительском компоненте, затем вызывается onPreviewKeyEvent() в дочернем компоненте. Используя это поведение, вы можете реализовать сочетания клавиш для всего экрана.

Дополнительные ресурсы

,

Когда пользователь фокусирует внимание на редактируемом текстовом компоненте, таком как TextField , и к устройству подключена аппаратная клавиатура, весь ввод обрабатывается системой. Вы можете предоставить сочетания клавиш, обрабатывая ключевые события.

Сочетания клавиш по умолчанию

Следующие сочетания клавиш доступны по умолчанию.

Сочетание клавиш Действие Composables, поддерживающие ярлык
Shift + Ctrl + Стрелка влево / Стрелка вправо Выделить текст до начала/конца слова BasicTextField , TextField
Shift + Ctrl + Стрелка вверх / Стрелка вниз Выделить текст до начала/конца абзаца BasicTextField , TextField
Shift + Alt + Стрелка вверх / Стрелка вниз или Shift + Meta + Стрелка влево / Стрелка вправо Выделить текст до начала/конца текста BasicTextField , TextField
Shift + Стрелка влево / Стрелка вправо Выберите персонажей BasicTextField , TextField
Ctrl + А Выбрать все 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 .

Нажатие клавиши отправляет два ключевых события. Один срабатывает, когда пользователь нажимает клавишу; другой срабатывает при отпускании ключа. Вы можете отличить два ключевых события, обратившись к атрибуту type объекта KeyEvent .

Возвращаемое значение лямбды onKeyEvent указывает, обработано ли событие ключа или нет. Возвращайте true если ваше приложение обрабатывает ключевое событие, которое останавливает распространение события.

В следующем фрагменте показано, как вызвать функцию doSomething() , когда пользователь отпускает клавишу S в компоненте Box :

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

События нажатия клавиши «Пробел» и «Ввод»

Клавиша «Пробел» и «Ввод» также запускают события щелчка. Например, пользователи могут переключать (воспроизводить или приостанавливать) воспроизведение мультимедиа с помощью клавиши пробела или клавиши Enter , обрабатывая события щелчка следующим образом:

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

Модификатор clickable перехватывает события нажатия клавиш и вызывает обратный вызов onClick() при нажатии клавиши пробела или клавиши Enter . Вот почему функция togglePausePlay() вызывается нажатием клавиши пробела или Enter во фрагменте.

Неиспользованные ключевые события

Неиспользованные ключевые события передаются из компонента, в котором произошло событие, во вмещающий внешний компонент. В приведенном ниже примере 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 является типичным. Следующий фрагмент позволяет пользователям перейти к следующему фокусируемому компоненту, нажав клавишу табуляции .

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 добавляет символ табуляции каждый раз, когда пользователи нажимают клавишу Tab , даже если событие нажатия клавиши обрабатывается с помощью модификатора onKeyEvent . Чтобы переместить фокус клавиатуры без добавления символов табуляции, обработайте событие клавиши перед запуском действий, связанных с событием клавиши, как во фрагменте. Лямбда onKeyPreviewEvent() перехватывает событие ключа, возвращая true .

Родительский компонент может перехватить ключевое событие, происходящее на его дочерних компонентах. В следующем фрагменте кода функцияпредварительного previewSKey() вызывается, когда пользователи нажимают клавишу S , вместо вызова функции actionForPreview() .

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

Лямбда-выражение onPreviewKeyEvent() для компонента Box также не срабатывает, когда пользователи нажимают клавишу Tab . Лямбда onPreviewKeyEvent() сначала вызывается в родительском компоненте, затем вызывается onPreviewKeyEvent() в дочернем компоненте. Используя это поведение, вы можете реализовать сочетания клавиш для всего экрана.

Дополнительные ресурсы