사용자가 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 수정자에 전달된 람다의 객체를 참조하여 각 키 이벤트의 정보를 가져올 수 있습니다.
키 입력은 두 개의 키 이벤트를 전송합니다.
하나는 사용자가 키를 누를 때 트리거되고 다른 하나는 키가 해제될 때 트리거됩니다.
두 키 이벤트를 구분할 수 있습니다.
type 속성을 참조하여 KeyEvent 객체의
onKeyEvent 람다의 반환 값은 키 이벤트가 처리되는지 여부를 나타냅니다.
앱이 키 이벤트를 처리하면 true를 반환하여 이벤트 전파를 중지합니다.
다음 스니펫은 사용자가 Box 구성요소에서 S 키를 해제할 때 doSomething() 함수
를 호출하는 방법을 보여줍니다.
Box( modifier = Modifier .onKeyEvent { if ( it.type == KeyEventType.KeyUp && it.key == Key.S ) { doSomething() true } else { false } } .focusable() ) { Text("Press S key") }
특수키
KeyEvent 객체에는 특수키가 눌렸는지 여부를 나타내는 다음과 같은 속성이 있습니다.
앱에서 처리하는 키 이벤트를 구체적으로 설명하세요.
다음 스니펫은 사용자가 S 키만 해제하는 경우에만 doSomething() 함수
를 호출합니다.
사용자가 특수키를 누르면,
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 키 클릭 이벤트
Spacebar 및 Enter 키도 클릭 이벤트를 트리거합니다. 예를 들어 사용자는 다음과 같이 클릭 이벤트를 처리하여 Spacebar 또는 Enter 키로 미디어 재생을 전환 (재생 또는 일시중지)할 수 있습니다.
MediaPlayer(modifier = Modifier.clickable { togglePausePlay() })
clickable 수정자는 키 이벤트를 가로채고 onClick() 콜백을 호출합니다. Spacebar 또는 Enter 키가 눌리면
이러한 이유로 스니펫에서 Spacebar 또는 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 키를 누를 때마다 탭 문자를 추가합니다.
탭 문자를 추가하지 않고 키보드 포커스를 이동하려면 스니펫과 같이 키 이벤트와 연결된 작업을 트리거하기 전에 키 이벤트를 처리하세요.
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()가 호출됩니다.
이 동작을 활용하여 화면 전체 키보드 단축키를 구현할 수 있습니다.
추가 리소스
- 키보드 단축키 도우미: 사용자가 앱에서 제공하는 키보드 단축키를 검색할 수 있는 시스템 화면입니다.