대형 화면 기기에서 사용자는 키보드, 마우스, 트랙패드, 스타일러스 또는 게임패드를 사용하여 앱과 상호작용하는 경우가 많습니다. 앱이 외부 기기의 입력을 허용하도록 사용 설정하려면 다음 단계를 따르세요.
- 실행취소의 경우 Ctrl+Z, 복사의 경우 Ctrl+C, 저장의 경우 Ctrl+S와 같은 기본 키보드 지원을 테스트합니다. 기본 단축키 목록은 키보드 작업 처리를 참고하세요.
- 고급 키보드 지원 테스트(예: Tab 키 및 화살표 키 키보드 탐색, Enter 키 텍스트 입력 확인, 미디어 앱에서 스페이스바 재생 및 일시중지)
- 마우스 오른쪽 버튼으로 클릭 시 컨텍스트 메뉴 표시, 마우스 오버 시 아이콘 변경, 맞춤 구성요소에서 마우스 휠/트랙패드 스크롤 이벤트를 비롯한 기본 마우스 상호작용을 테스트합니다.
- 스타일러스, 게임 컨트롤러, 음악 앱 MIDI 컨트롤러와 같은 특정 앱에 사용되는 입력 장치 테스트
- 데스크톱 환경에서 앱을 돋보이게 만들 수 있는 고급 입력 지원 기능 고려(예: DJ 앱의 크로스페이더로 사용되는 터치패드, 게임용 마우스 캡처, 키보드 중심의 사용자를 위한 단축키)
키보드
앱이 키보드 입력에 반응하는 방식을 통해 대형 화면 사용자 환경을 구현할 수 있습니다. 키보드 입력에는 탐색, 키 입력, 단축키의 세 가지 종류가 있습니다.
탐색
키보드 탐색은 터치 중심 앱에서는 거의 구현되지 않지만, 사용자는 앱을 사용하면서 키보드가 있으면 키보드를 이용한 이동이 가능할 것으로 기대합니다. 키보드 탐색은 휴대전화, 태블릿, 폴더블, 데스크톱 기기에서 접근성과 관련한 요구사항이 있는 사용자에게 필수적일 수 있습니다.
많은 앱에서 화살표 키와 Tab 탐색은 Android 프레임워크에 의해 자동으로 처리됩니다. 예를 들어 Button
는 기본적으로 포커스가 가능하며, 키보드 탐색은 일반적으로 추가 코드 없이 작동해야 합니다. 기본적으로 포커스가 가능하지 않은 뷰에 키보드 탐색을 사용 설정하려면 이러한 뷰를 포커스 가능으로 표시합니다. 프로그래매틱 방식으로 또는 XML에서 처리할 수 있습니다.
Kotlin
yourView.isFocusable = true
자바
yourView.setFocusable(true);
또는 다음과 같이 레이아웃 파일에서 focusable
속성을 설정할 수 있습니다.
android:focusable="true"
자세한 내용은 포커스 처리를 참고하세요.
포커스가 사용 설정되면 Android 프레임워크는 위치를 기반으로 포커스 가능한 모든 뷰의 탐색 매핑을 생성합니다. 이 매핑은 일반적으로 예상대로 작동하며 추가 개발이 필요하지 않습니다. 기본 매핑이 앱의 요구에 적합하지 않을 때는 다음과 같이 매핑을 재정의할 수 있습니다.
Kotlin
// Arrow keys yourView.nextFocusLeftId = R.id.view_to_left yourView.nextFocusRightId = R.id.view_to_right yourView.nextFocusTopId = R.id.view_above yourView.nextFocusBottomId = R.id.view_below // Tab key yourView.nextFocusForwardId = R.id.next_view
자바
// Arrow keys yourView.setNextFocusLeftId(R.id.view_to_left); yourView.setNextFocusRightId(R.id.view_to_left); yourView.setNextFocusTopId(R.id.view_to_left); yourView.setNextFocusBottomId(R.id.view_to_left); // Tab key yourView.setNextFocusForwardId(R.id.next_view);
키보드만 사용하여 앱의 모든 UI 요소에 대한 액세스를 테스트합니다. 자주 사용되는 요소는 마우스나 터치 입력 없이 액세스할 수 있어야 합니다.
접근성과 관련한 요구사항을 가진 사용자에게는 키보드 지원이 필수적일 수 있습니다.
키 입력
, EditText
,와 같이 화면 가상 키보드 (IME)로 처리되는 텍스트 입력의 경우 앱은 추가 개발 작업 없이 대형 화면 기기에서 예상대로 작동해야 합니다. 프레임워크에서 예상할 수 없는 키 입력의 경우 앱이 동작을 직접 처리해야 합니다. 이는 맞춤 뷰가 있는 앱의 경우에 특히 그렇습니다.
몇 가지 예로 Enter 키를 사용하여 메시지를 보내는 채팅 앱, 스페이스바를 사용하여 재생을 시작/중지하는 미디어 앱, w, a, s, d 키로 움직임을 제어하는 게임이 있습니다.
대부분의 앱은 onKeyUp()
콜백을 재정의하고 수신된 키 코드마다 예상되는 동작을 추가합니다.
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when (keyCode) { KeyEvent.KEYCODE_ENTER -> { sendChatMessage() true } KeyEvent.KEYCODE_SPACE -> { playOrPauseMedia() true } else -> super.onKeyUp(keyCode, event) } }
자바
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER) { sendMessage(); return true; } else if (KeyEvent.KEYCODE_SPACE){ playOrPauseMedia(); return true; } else { return super.onKeyUp(keyCode, event); } }
키가 해제되면 onKeyUp
이벤트가 발생합니다. 콜백을 사용하면 키를 누른 채로 있거나 천천히 손을 뗄 때 앱이 여러 onKeyDown
이벤트를 처리할 필요가 없습니다. 키가 눌리는 순간이나 사용자가 키를 누르고 있는지 감지해야 하는 게임과 앱은 onKeyDown
이벤트를 수신 대기하고 반복된 onKeyDown
이벤트를 자체적으로 처리할 수 있습니다.
자세한 내용은 키보드 작업 처리를 참고하세요.
단축키
하드웨어 키보드를 사용할 때는 Ctrl, Alt, Shift, Meta 키가 포함된 일반적인 단축키가 필요합니다. 앱에서 단축키를 구현하지 않으면 사용자가 앱 사용 환경에 불편을 겪을 수 있습니다. 또한 고급 사용자는 개별 앱별로 자주 사용하는 작업을 위한 단축키도 유용하게 사용합니다. 단축키가 있으면 앱을 편리하게 사용할 수 있으며 단축키가 없는 앱과 차별화됩니다.
몇 가지 일반적인 단축키로는 Ctrl+S (저장), Ctrl+Z(실행취소), Ctrl+Shift+Z (다시 실행)가 있습니다. 기본 단축키 목록은 키보드 작업 처리를 참고하세요.
dispatchKeyShortcutEvent()
를 구현하여 지정된 키 코드의 모든 키 조합 (Alt, Ctrl, Shift, Meta)을 가로채면 단축키를 사용 설정할 수 있습니다.
특정 수정자 키를 확인하려면 다음을 사용하세요.
KeyEvent.isCtrlPressed()
,KeyEvent.isShiftPressed()
,KeyEvent.isAltPressed()
,KeyEvent.isMetaPressed()
또는
Kotlin
override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean { return when (event.keyCode) { KeyEvent.KEYCODE_O -> { openFile() // Ctrl+O, Shift+O, Alt+O true } KeyEvent.KEYCODE_Z-> { if (event.isCtrlPressed) { if (event.isShiftPressed) { redoLastAction() // Ctrl+Shift+Z pressed true } else { undoLastAction() // Ctrl+Z pressed true } } } else -> { return super.dispatchKeyShortcutEvent(event) } } }
자바
@Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_O) { openFile(); // Ctrl+O, Shift+O, Alt+O return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_Z) { if (event.isCtrlPressed()) { if (event.isShiftPressed()) { redoLastAction(); return true; } else { undoLastAction(); return true; } } } return super.dispatchKeyShortcutEvent(event); }
다른 키 입력 처리 (예: onKeyUp()
및 onKeyDown()
)에서 단축키 코드를 분리하면 모든 경우에 특수키 확인을 수동으로 구현할 필요 없이 기본적으로 특수키를 허용합니다. 모든 수정자 키 조합을 허용하면 다양한 키보드 레이아웃 및 운영체제에 익숙한 사용자에게 더 편리할 수 있습니다.
하지만 KeyEvent.isCtrlPressed()
, KeyEvent.isShiftPressed()
또는 KeyEvent.isAltPressed()
를 확인하여 onKeyUp()
에서 바로가기를 구현할 수도 있습니다. 수정된 키 동작이 단축키보다는 앱 동작에 관한 변경사항이라면 이 방법이 유지관리하기 더 쉬울 수 있습니다. 예를 들어 게임에서 W가 '앞으로 걷기'를 의미하고 Shift+W가 '앞으로 달리기'를 의미할 때
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when(keyCode) { KeyEvent.KEYCODE_W-> { if (event.isShiftPressed) { if (event.isCtrlPressed) { flyForward() // Ctrl+Shift+W pressed true } else { runForward() // Shift+W pressed true } } else { walkForward() // W pressed true } } else -> super.onKeyUp(keyCode, event) } }
자바
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_W) { if (event.isShiftPressed()) { if (event.isCtrlPressed()) { flyForward(); // Ctrl+Shift+W pressed return true; } else { runForward(); // Shift+W pressed return true; } } else { walkForward(); return true; } } return super.onKeyUp(keyCode, event); }
단축키 도우미도 참고하세요.
스타일러스
대부분의 대형 화면 기기에는 스타일러스가 함께 제공됩니다. Android 앱은 스타일러스를 터치 스크린 입력으로 처리합니다. 일부 기기에는 Wacom Intuos와 같은 USB 또는 블루투스 그리기 테이블이 있을 수도 있습니다. Android 앱은 블루투스 입력을 수신할 수 있지만 USB 입력은 수신할 수 없습니다.
스타일러스 이벤트는 View#onTouchEvent()
또는 View#onGenericMotionEvent()
에 의해 터치스크린 이벤트로 보고되며 SOURCE_STYLUS
유형의 MotionEvent#getSource()
를 포함합니다.
MotionEvent
객체에는 이벤트에 관한 정보가 포함됩니다.
MotionEvent#getToolType()
은 디스플레이와 접촉한 도구에 따라TOOL_TYPE_FINGER
,TOOL_TYPE_STYLUS
또는TOOL_TYPE_ERASER
를 반환합니다.MotionEvent#getPressure()
는 스타일러스 펜 (지원되는 경우)에 적용되는 물리적 압력을 보고합니다.MotionEvent.AXIS_TILT
및MotionEvent.AXIS_ORIENTATION
이 포함된MotionEvent#getAxisValue()
는 스타일러스의 물리적 기울기와 방향을 제공합니다 (지원되는 경우).
이전 포인트
Android는 입력 이벤트를 일괄 처리하며 프레임당 한 번씩 전달합니다. 스타일러스는 디스플레이보다 훨씬 자주 이벤트를 보고할 수 있습니다. 그리기 앱을 만들 때는 다음과 같은 getHistorical
API를 사용하여 최근에 발생한 이벤트를 확인합니다.
MotionEvent#getHistoricalX()
MotionEvent#getHistoricalY()
MotionEvent#getHistoricalPressure()
MotionEvent#getHistoricalAxisValue()
손바닥 움직임 무시
사용자는 스타일러스를 사용하여 앱에서 그리거나 쓰거나 상호작용할 때 손바닥으로 화면을 터치하기도 합니다. 이러한 터치 이벤트 (ACTION_DOWN
또는 ACTION_POINTER_DOWN
으로 설정)를 시스템이 인식하여 의도치 않은 터치로 무시하기 전에 이벤트가 앱에 보고되는 경우가 있습니다.
Android는 MotionEvent
를 전달하여 손바닥 터치 이벤트를 취소합니다. 앱이 ACTION_CANCEL
을 수신하면 동작을 취소합니다. 앱이 ACTION_POINTER_UP
을 수신하면 FLAG_CANCELED
가 설정되었는지 확인합니다. 설정되어 있는 경우 동작을 취소합니다.
FLAG_CANCELED
만 확인해서는 안 됩니다. Android 13 (API 수준 33) 이상에서는 시스템이 ACTION_CANCEL
이벤트에 FLAG_CANCELED
를 설정하지만 이전 Android 버전에서는 플래그를 설정하지 않습니다.
Android 12
Android 12 (API 수준 32) 이하에서는 단일 포인터 터치 이벤트에만 손바닥 거부 감지가 가능합니다. 손바닥 터치가 유일한 포인터인 경우 시스템은 모션 이벤트 객체에 ACTION_CANCEL
을 설정하여 이벤트를 취소합니다. 다른 포인터가 다운이면 시스템은 ACTION_POINTER_UP
을 설정하는데 이는 손바닥 거부를 감지하는 데 충분하지 않습니다.
Android 13
Android 13(API 수준 33) 이상에서 손바닥 터치가 유일한 포인터인 경우 시스템은 모션 이벤트 객체에 ACTION_CANCEL
및 FLAG_CANCELED
를 설정하여 이벤트를 취소합니다. 다른 포인터가 다운이면 시스템은 ACTION_POINTER_UP
및 FLAG_CANCELED
를 설정합니다.
앱에서 ACTION_POINTER_UP
으로 모션 이벤트를 수신할 때마다 FLAG_CANCELED
를 확인하여 이벤트가 손바닥 거부 또는 다른 이벤트 취소를 나타내는지 확인합니다.
메모 작성 앱
ChromeOS에는 등록된 메모 작성 앱을 사용자에게 표시하는 특별한 인텐트가 있습니다. 앱을 메모 작성 앱으로 등록하려면 앱 매니페스트에 다음을 추가합니다.
<intent-filter>
<action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
앱이 시스템에 등록되면 사용자는 이 앱을 기본 메모 작성 앱으로 선택할 수 있습니다. 새 메모가 요청되면 앱에서 스타일러스 입력을 위한 빈 메모를 생성할 것입니다. 사용자가 이미지(예: 스크린샷 또는 다운로드한 이미지)에 주석을 추가하려는 경우 content://
URI가 있는 하나 이상의 항목이 포함된 ClipData
를 사용하여 앱이 실행됩니다. 앱은 처음 첨부된 이미지를 배경 이미지로 사용하는 메모를 생성하고 사용자가 스타일러스를 사용하여 화면에 그릴 수 있는 모드로 전환해야 합니다.
스타일러스 없이 메모 작성 인텐트 테스트
[TBD 섹션 삭제]
앱이 활성화된 스타일러스 없이 메모 작성 인텐트에 올바르게 응답하는지 테스트하려면 다음 방법을 사용하여 ChromeOS에서 메모 작성 옵션을 표시합니다.
- 개발자 모드로 전환하여 기기를 쓰기 가능하게 만듭니다.
- Ctrl+Alt+F2를 눌러 터미널을 엽니다.
- 명령어
sudo vi /etc/chrome_dev.conf
를 실행합니다. i
를 눌러 파일 끝의 새 줄에--ash-enable-palette
를 추가합니다.- Esc 키를 누른 후 :, w, q를 입력하고 Enter 키를 눌러 저장합니다.
- Ctrl+Alt+F1을 눌러 일반 ChromeOS UI로 돌아갑니다.
- 로그아웃했다가 다시 로그인
이제 실행기에 스타일러스 메뉴가 있을 것입니다.
- 실행기에서 스타일러스 버튼을 탭하고 새 메모를 선택합니다. 그러면 비어 있는 그리기 메모가 열립니다.
- 스크린샷을 찍습니다. 실행기에서 스타일러스 버튼 > 화면 캡처를 선택하거나 이미지를 다운로드합니다. 알림에 이미지에 주석 달기 옵션이 있을 것입니다. 그러면 주석을 추가할 준비가 된 이미지와 함께 앱이 실행됩니다.
마우스 및 터치패드 지원
대부분의 앱은 일반적으로 세 가지 대형 화면 중심 이벤트, 즉 마우스 오른쪽 버튼 클릭, 마우스 오버, 드래그 앤 드롭만 처리하면 됩니다.
마우스 오른쪽 버튼 클릭
목록 항목을 길게 터치하는 것과 같이 앱이 컨텍스트 메뉴를 표시하게 하는 작업은 마우스 오른쪽 버튼 클릭 이벤트에도 반응해야 합니다.
마우스 오른쪽 버튼 클릭 이벤트를 처리하려면 앱에서 View.OnContextClickListener
를 등록해야 합니다.
Kotlin
yourView.setOnContextClickListener { showContextMenu() true }
자바
yourView.setOnContextClickListener(v -> { showContextMenu(); return true; });
컨텍스트 메뉴 구성에 관한 자세한 내용은 컨텍스트 메뉴 만들기를 참고하세요.
마우스 오버
마우스 오버 이벤트를 처리하여 앱 레이아웃을 세련되고 사용하기 쉽게 만들 수 있습니다. 이는 맞춤 조회수:
Kotlin
// Change the icon to a "hand" pointer on hover. // Highlight the view by changing the background. yourView.setOnHoverListener { view, _ -> addVisualHighlighting(true) view.pointerIcon = PointerIcon.getSystemIcon(view.context, PointerIcon.TYPE_HAND) true // Listener consumes the event. }
자바
// Change the icon to a "hand" pointer on hover. // Highlight the view by changing the background. yourView.setOnHoverListener((view, event) -> { addVisualHighlighting(true); view.setPointerIcon( PointerIcon.getSystemIcon(view.getContext(), PointerIcon.TYPE_HAND) ); return true; // Listener consumes the event. });
이와 관련된 가장 일반적인 두 가지 예는 다음과 같습니다.
- 마우스 포인터 아이콘을 변경하여 요소에 클릭 가능 또는 수정 가능과 같은 상호작용 동작이 있는지 사용자에게 표시
- 큰 목록 또는 그리드의 항목 위에 마우스 포인터를 가져가면 항목에 시각적 피드백 추가
드래그 앤 드롭
멀티 윈도우 환경에서 사용자는 앱 간에 항목을 드래그 앤 드롭할 수 있을 것으로 기대합니다. 이러한 기대는 화면 분할 모드의 태블릿, 휴대전화, 폴더블뿐만 아니라 데스크톱 기기에도 적용됩니다.
사용자가 항목을 앱으로 드래그할 가능성이 있는지 고려합니다. 예를 들어 사진 편집기에서는 사진을 수신해야 하고 오디오 플레이어에서는 오디오 파일을 수신해야 하며 그리기 프로그램에서는 사진을 수신해야 합니다.
드래그 앤 드롭 지원을 추가하려면 드래그 앤 드롭 사용 설정 을 참고하고 ChromeOS의 Android - 드래그 앤 드롭 구현 블로그 게시물을 살펴보세요.
ChromeOS의 특별 고려사항
- 앱 외부에서 드래그한 항목에 액세스하려면
requestDragAndDropPermissions()
를 사용하여 권한을 요청해야 합니다. 항목을 다른 애플리케이션으로 드래그하려면 항목에
View.DRAG_FLAG_GLOBAL
플래그가 있어야 합니다.
고급 포인터 지원
마우스 및 터치패드 입력의 고급 처리를 실행하는 앱은
View#onGenericMotionEvent()
를 사용하고 [MotionEvent.getSource()
][] 를 사용하여 SOURCE_MOUSE
와 SOURCE_TOUCHSCREEN
를 구분합니다.
MotionEvent
객체를 검토하여 필요한 동작을 구현합니다.
- 움직임은
ACTION_HOVER_MOVE
이벤트를 생성합니다. - 버튼은
ACTION_BUTTON_PRESS
및ACTION_BUTTON_RELEASE
이벤트를 생성합니다.getButtonState()
를 사용하여 모든 마우스 및 트랙패드 버튼의 현재 상태를 확인할 수도 있습니다. - 마우스 휠 스크롤은
ACTION_SCROLL
이벤트를 생성합니다.
게임 컨트롤러
일부 대형 화면 Android 기기는 최대 4개의 게임 컨트롤러를 지원합니다. 표준 Android 게임 컨트롤러 API를 사용하여 게임 컨트롤러를 처리합니다 (게임 컨트롤러 지원 참고).
게임 컨트롤러 버튼은 일반 매핑에 따라 일반 값에 매핑됩니다. 하지만 모든 게임 컨트롤러 제조업체가 동일한 매핑 규칙을 따르는 것은 아닙니다. 사용자가 널리 사용되는 다양한 컨트롤러 매핑을 선택하도록 허용하면 훨씬 더 나은 환경을 제공할 수 있습니다. 자세한 내용은 게임패드 버튼 누름 처리를 참고하세요.
입력 변환 모드
ChromeOS는 기본적으로 입력 변환 모드를 사용 설정합니다. 대부분의 Android 앱에서 이 모드를 사용하면 앱이 데스크톱 환경에서 예상대로 작동합니다. 몇 가지 예로는 터치패드에서 두 손가락 스크롤, 마우스 휠 스크롤, 창 좌표에 원시 디스플레이 좌표 매핑 자동 사용 설정 등이 있습니다. 일반적으로 앱 개발자는 이러한 동작을 직접 구현할 필요가 없습니다.
앱에서 맞춤 입력 동작을 구현하거나(예: 터치패드에서 두 손가락 모으기 동작의 맞춤 정의) 이러한 입력 변환이 앱에서 예상하는 입력 이벤트를 제공하지 않는다면 Android 매니페스트에 다음 태그를 추가하여 입력 변환 모드를 사용 중지할 수 있습니다.
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />