Android와 ChromeOS는 Android 및 iOS에서 작동하는 앱을 빌드하는 데 도움이 되는 다양한 API를
사용자에게 탁월한 스타일러스 환경을 제공합니다. 이
MotionEvent
클래스가 노출됨
스타일러스 압력, 스타일러스 압력 등 화면과의 스타일러스 상호작용에 관한 정보
방향, 기울기, 마우스 오버, 손바닥 감지 지연 시간이 짧은 그래픽 및 모션
예측 라이브러리는 스타일러스 화면 렌더링을 개선하여
종이와 펜으로 읽는 것 같은 자연스러운 경험입니다.
MotionEvent
MotionEvent
클래스는 위치와 같은 사용자 입력 상호작용을 나타냅니다.
화면의 터치 포인터의 움직임도 제어할 수 있습니다. 스타일러스 입력의 경우 MotionEvent
압력, 방향, 기울기, 마우스 오버 데이터도 노출합니다.
이벤트 데이터
</ph>MotionEvent
데이터에 액세스하려면
onTouchListener의 인스턴스입니다.
Kotlin
val onTouchListener = View.OnTouchListener { view, event -> // Process motion event. }
자바
View.OnTouchListener listener = (view, event) -> { // Process motion event. };
리스너는 시스템에서 MotionEvent
객체를 수신하므로 앱이 다음을 실행할 수 있습니다.
처리할 수 있습니다
MotionEvent
객체는 UI의 다음과 같은 측면과 관련된 데이터를 제공합니다.
이벤트를 사용합니다.
- 작업: 기기와의 물리적 상호작용(화면 터치) 포인터를 화면 표면 위로 이동, 포인터를 화면 위로 가져옴 표면
- 포인터: 화면과 상호작용하는 객체 식별자(손가락, 스타일러스, 마우스
- 축: 데이터 유형 — x 및 y 좌표, 압력, 기울기, 방향, 및 마우스 오버 (거리)
작업
스타일러스 지원을 구현하려면 사용자가 어떤 작업을 하는지 이해해야 합니다. 있습니다.
MotionEvent
는 모션을 정의하는 다양한 ACTION
상수를 제공합니다.
이벤트를 수신합니다. 스타일러스에 가장 중요한 작업은 다음과 같습니다.
작업 | 설명 |
---|---|
ACTION_DOWN ACTION_POINTER_DOWN |
포인터가 화면에 닿습니다. |
ACTION_MOVE | 화면에서 포인터가 움직입니다. |
ACTION_UP ACTION_POINTER_UP |
포인터가 더 이상 화면에 닿지 않습니다. |
ACTION_CANCEL | 이전 또는 현재 모션 세트를 취소해야 하는 경우입니다. |
ACTION_DOWN
시 앱에서 새로운 획 시작과 같은 작업을 실행할 수 있습니다.
ACTION_MOVE,
로 획을 그리고
ACTION_UP
가 트리거됩니다.
특정 작업의 ACTION_DOWN
에서 ACTION_UP
까지 MotionEvent
작업 집합입니다.
포인터를 모션 세트라고 합니다
포인터
대부분의 화면은 멀티 터치입니다. 시스템은 각 손가락에 포인터를 할당하지만 스타일러스, 마우스 또는 화면과 상호작용하는 기타 포인팅 객체입니다. 포인터 index를 사용하면 특정 포인터에 대한 축 정보를 가져올 수 있습니다. 터치하는 첫 번째 손가락의 위치 또는 두 번째 손가락의 위치.
포인터 인덱스 범위는 0부터
MotionEvent#pointerCount()
드림
빼세요.
포인터의 축 값은 getAxisValue(axis,
pointerIndex)
메서드로 액세스할 수 있습니다.
포인터 인덱스가 생략되면 시스템은 첫 번째
있습니다.
MotionEvent
객체에는 사용 중인 포인터 유형에 관한 정보가 포함됩니다. 나
포인터 인덱스를 반복하고
getToolType(pointerIndex)
드림
메서드를 사용하여 축소하도록 요청합니다.
포인터에 관한 자세한 내용은 멀티 터치 처리를 참고하세요. 동작을 사용합니다.
스타일러스 입력
다음을 사용하여 스타일러스 입력을 필터링할 수 있습니다.
TOOL_TYPE_STYLUS
:
Kotlin
val isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex)
자바
boolean isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex);
또한 스타일러스는 지우개로 사용된다고 보고할 수 있습니다.
TOOL_TYPE_ERASER
:
Kotlin
val isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex)
Java
boolean isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex);
스타일러스 축 데이터
ACTION_DOWN
및 ACTION_MOVE
는 스타일러스에 관한 축 데이터, 즉 x와
y 좌표, 압력, 방향, 기울기, 마우스 오버
이 데이터에 액세스할 수 있도록 MotionEvent
API는 다음을 제공합니다.
getAxisValue(int)
,
여기서 매개변수는 다음 축 식별자 중 하나입니다.
축 | getAxisValue() 의 반환 값 |
---|---|
AXIS_X |
모션 이벤트의 X 좌표입니다. |
AXIS_Y |
모션 이벤트의 Y 좌표입니다. |
AXIS_PRESSURE |
터치 스크린 또는 터치패드의 경우 손가락, 스타일러스 또는 기타 포인터로 적용된 압력입니다. 마우스나 트랙볼의 경우 기본 버튼을 누르면 1, 누르지 않으면 0입니다. |
AXIS_ORIENTATION |
터치 스크린 또는 터치패드의 경우 기기의 수직면을 기준으로 손가락, 스타일러스 또는 기타 포인터의 방향입니다. |
AXIS_TILT |
라디안으로 표시되는 스타일러스의 기울기 각도입니다. |
AXIS_DISTANCE |
화면과 스타일러스의 거리입니다. |
예를 들어 MotionEvent.getAxisValue(AXIS_X)
는 다음 함수의 x 좌표를 반환합니다.
있습니다.
멀티 터치 처리도 참고하세요. 동작을 사용합니다.
위치
다음 호출을 사용하여 포인터의 x 및 y 좌표를 가져올 수 있습니다.
MotionEvent#getAxisValue(AXIS_X)
또는MotionEvent#getX()
MotionEvent#getAxisValue(AXIS_Y)
또는MotionEvent#getY()
압력
다음 명령어를 사용하여 포인터 압력을 가져올 수 있습니다.
MotionEvent#getAxisValue(AXIS_PRESSURE)
또는 첫 번째 포인터의 경우
MotionEvent#getPressure()
터치 스크린 또는 터치패드의 압력 값은 0 (아니요 1)이지만 화면에 따라 더 높은 값이 반환될 수 있습니다. 있습니다.
를 통해 개인정보처리방침을 정의할 수 있습니다.방향
방향은 스타일러스가 가리키는 방향을 나타냅니다.
포인터 방향은 getAxisValue(AXIS_ORIENTATION)
또는
getOrientation()
를 누릅니다.
스타일러스의 경우 방향은 0에서 파이 (π) 사이의 라디안 값으로 반환됩니다. 또는 0에서 -pi를 시계 반대 방향으로 설정합니다.
방향을 사용하면 실제 브러시를 구현할 수 있습니다. 예를 들어 스타일러스가 평면 브러시를 나타내는 경우 평면 브러시의 너비는 사용합니다.
기울기
기울기는 화면을 기준으로 스타일러스의 경사를 측정합니다.
기울기는 스타일러스의 양의 각도(라디안)를 반환합니다. 여기서 0은 파이/2는 화면에 직각이고 π/2는 표면에서 평평합니다.
기울기 각도는 getAxisValue(AXIS_TILT)
(
첫 번째 포인터로 이동).
기울기를 사용하면 다음과 같이 실제 도구에 최대한 가깝게 재현할 수 있습니다. 기울어진 연필로 음영을 모방합니다.
를 통해 개인정보처리방침을 정의할 수 있습니다.마우스 오버
화면과 스타일러스의 거리는 다음을 사용하여 구할 수 있습니다.
getAxisValue(AXIS_DISTANCE)
이 메서드는 0.0에서 값을 반환합니다.
스타일러스가 화면에서 멀어짐에 따라 더 높은 값으로 조정됨 마우스 오버
화면과 스타일러스의 촉 (포인트) 사이의 거리는
제조업체입니다. 구현은
앱에 중요한 기능의 경우 정확한 값에 의존하지 마세요.
스타일러스 마우스 오버를 사용하면 브러시의 크기를 미리 보거나 버튼이 선택됩니다.
참고: Compose는 UI 요소의 상호작용 상태에 영향을 주는 수정자를 제공합니다.
hoverable
: 포인터 들어가기 및 나가기 이벤트를 사용하여 마우스 오버가 가능한 구성요소를 구성합니다.indication
: 상호작용이 발생할 때 이 구성요소의 시각적 효과를 그립니다.
손바닥 움직임 무시, 탐색, 원치 않는 입력
멀티 터치 화면에서 원치 않는 터치가 등록될 수 있습니다. 예를 들어
사용자가 필기를 할 때 자연스럽게 손바닥을 화면에 대고 지지합니다.
손바닥 움직임 무시는 이러한 동작을 감지하고
마지막 MotionEvent
세트를 취소해야 합니다.
따라서 원치 않는 터치가 발생할 수 있도록 사용자 입력 기록을 유지해야 합니다. 화면에서 제거될 수 있고 합법적인 사용자 입력이 있습니다.
ACTION_CANCEL 및 FLAG_CANCELED
ACTION_CANCEL
및
FLAG_CANCELED
값:
두 가지 모두 이전 MotionEvent
세트가
취소되므로, 예를 들어 마지막 ACTION_DOWN
에서 취소된 것을 실행취소할 수 있습니다.
획을 정의할 수 있습니다.
ACTION_CANCEL
Android 1.0(API 수준 1)에 추가되었습니다.
ACTION_CANCEL
은 이전 모션 이벤트 세트를 취소해야 함을 나타냅니다.
다음 중 하나라도 감지되면 ACTION_CANCEL
이 트리거됩니다.
- 탐색 동작
- 손바닥 움직임 무시
ACTION_CANCEL
가 트리거되면 다음을 사용하여 활성 포인터를 식별해야 합니다.
getPointerId(getActionIndex())
그런 다음 입력 기록에서 해당 포인터로 만든 획을 삭제하고 장면을 다시 렌더링합니다.
FLAG_CANCELED
Android 13(API 수준 33)에 추가되었습니다.
FLAG_CANCELED
드림
위로 올라가는 포인터가 의도치 않은 사용자 터치였음을 나타냅니다. 플래그는
일반적으로 사용자가 실수로 화면을 터치할 때 설정
손바닥을 화면에 대면 됩니다.
플래그 값에 액세스하는 방법은 다음과 같습니다.
Kotlin
val cancel = (event.flags and FLAG_CANCELED) == FLAG_CANCELED
자바
boolean cancel = (event.getFlags() & FLAG_CANCELED) == FLAG_CANCELED;
플래그가 설정된 경우 마지막 MotionEvent
집합을 실행취소해야 합니다.
이 포인터에서 ACTION_DOWN
입니다.
ACTION_CANCEL
과 마찬가지로 포인터는 getPointerId(actionIndex)
로 찾을 수 있습니다.
전체 화면, 더 넓은 화면, 탐색 동작
앱이 전체 화면이며 가장자리 근처에 실행 가능한 요소가 있는 경우(예: 캔버스에 액세스할 수도 있습니다. 내비게이션을 표시하거나 앱을 백그라운드로 이동하면 영향을 주지 않습니다.
동작으로 인해 앱에서 원치 않는 터치가 트리거되지 않도록 하려면
인셋과
ACTION_CANCEL
입니다.
손바닥 움직임 무시, 탐색, 원치 않는 입력도 참고하세요. 섹션으로 이동합니다.
사용
setSystemBarsBehavior()
드림
메서드와
BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
/
WindowInsetsController
탐색 동작으로 원치 않는 터치 이벤트가 발생하지 않도록 할 수 있습니다.
Kotlin
// Configure the behavior of the hidden system bars. windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
Java
// Configure the behavior of the hidden system bars. windowInsetsController.setSystemBarsBehavior( WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE );
인셋 및 동작 관리에 관한 자세한 내용은 다음을 참고하세요.
짧은 지연 시간
지연 시간은 하드웨어, 시스템, 애플리케이션에서 처리하는 데 필요한 시간입니다. 사용자 입력을 렌더링할 수 있습니다
지연 시간 = 하드웨어 및 OS 입력 처리 + 앱 처리 + 시스템 합성
- 하드웨어 렌더링
지연 시간 소스
- 터치 스크린 (하드웨어)에 스타일러스 등록: 초기 무선 연결 스타일러스와 OS가 등록 및 동기화를 위해 통신할 때
- 터치 샘플링 레이트 (하드웨어): 터치스크린이 초당 표시되는 횟수 포인터가 표면에 닿는지 확인합니다(60~1000Hz).
- 입력 처리 (앱): 색상, 그래픽 효과, 변환 적용 영향을 줄 수 있습니다.
- 그래픽 렌더링(OS + 하드웨어): 버퍼 전환, 하드웨어 처리
지연 시간이 짧은 그래픽
지연 시간이 짧은 Jetpack 그래픽 라이브러리 사용자 입력과 화면 렌더링 사이의 처리 시간을 줄일 수 있습니다.
라이브러리는 다중 버퍼 렌더링을 피하여 처리 시간을 단축하고 즉, 프런트 버퍼 렌더링 기법을 활용하여 화면
전면 버퍼 렌더링
전면 버퍼는 화면이 렌더링에 사용하는 메모리입니다. 가장 가깝습니다. 앱에 직접 그림을 그릴 수 있습니다. 지연 시간이 짧은 라이브러리를 사용하면 전면 버퍼에 직접 렌더링할 수 있습니다. 이렇게 하면 일반적인 다중 버퍼 렌더링에서 발생할 수 있는 버퍼 스와핑 방지 이중 버퍼 렌더링 (가장 일반적인 사례)을 사용할 수 있습니다.
전면 버퍼 렌더링은 전체 화면을 새로 고치는 데 사용하도록 설계되지 않았습니다. 다음으로 바꿉니다. 앱이 버퍼로 콘텐츠를 렌더링하고, 이 버퍼로부터 있습니다. 결과적으로는 한 번에 여러 번 테어링 (아래 참고)
지연 시간이 짧은 라이브러리는 Android 10 (API 수준 29) 이상에서 사용할 수 있습니다. Android 10 (API 수준 29) 이상을 실행하는 ChromeOS 기기에서 지원됩니다.
종속 항목
짧은 지연 시간 라이브러리는 전면 버퍼 렌더링을 위한 구성요소를 제공합니다.
있습니다. 라이브러리가 앱 모듈에 종속 항목으로 추가됩니다.
build.gradle
파일:
dependencies {
implementation "androidx.graphics:graphics-core:1.0.0-alpha03"
}
GLFrontBufferRenderer 콜백
지연 시간이 짧은 라이브러리에는
GLFrontBufferRenderer.Callback
드림
인터페이스에 포함되어 있으며, 이 클래스는 다음 메서드를 정의합니다.
지연 시간이 짧은 라이브러리는 사용하는 데이터 유형에 대해 독단적이지 않습니다.
GLFrontBufferRenderer
그러나 라이브러리는 이 데이터를 수백 개의 데이터 포인트 스트림으로 처리합니다. 따라서 메모리 사용량과 할당을 최적화하도록 데이터를 설계해야 합니다.
콜백
렌더링 콜백을 사용 설정하려면 GLFrontBufferedRenderer.Callback
와
onDrawFrontBufferedLayer()
및 onDrawDoubleBufferedLayer()
를 재정의합니다.
GLFrontBufferedRenderer
는 콜백을 사용하여 데이터를 최대한 빠르게 렌더링합니다.
있습니다.
Kotlin
val callback = object: GLFrontBufferedRenderer.Callback<DATA_TYPE> { override fun onDrawFrontBufferedLayer( eglManager: EGLManager, bufferInfo: BufferInfo, transform: FloatArray, param: DATA_TYPE ) { // OpenGL for front buffer, short, affecting small area of the screen. } override fun onDrawMultiDoubleBufferedLayer( eglManager: EGLManager, bufferInfo: BufferInfo, transform: FloatArray, params: Collection<DATA_TYPE> ) { // OpenGL full scene rendering. } }
Java
GLFrontBufferedRenderer.Callback<DATA_TYPE> callbacks = new GLFrontBufferedRenderer.Callback<DATA_TYPE>() { @Override public void onDrawFrontBufferedLayer(@NonNull EGLManager eglManager, @NonNull BufferInfo bufferInfo, @NonNull float[] transform, DATA_TYPE data_type) { // OpenGL for front buffer, short, affecting small area of the screen. } @Override public void onDrawDoubleBufferedLayer(@NonNull EGLManager eglManager, @NonNull BufferInfo bufferInfo, @NonNull float[] transform, @NonNull Collection<? extends DATA_TYPE> collection) { // OpenGL full scene rendering. } };
GLFrontBufferedRenderer 인스턴스 선언
다음을 제공하여 GLFrontBufferedRenderer
준비 SurfaceView
및
사용할 수 있습니다. GLFrontBufferedRenderer
는 렌더링을 최적화합니다.
콜백을 사용하여 전면 및 이중 버퍼에 전달합니다.
Kotlin
var glFrontBufferRenderer = GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks)
Java
GLFrontBufferedRenderer<DATA_TYPE> glFrontBufferRenderer = new GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks);
렌더링
renderFrontBufferedLayer()
드림
메서드를 호출하여 onDrawFrontBufferedLayer()
콜백을 트리거합니다.
이중 버퍼 렌더링은
commit()
드림
함수를 사용하여 onDrawMultiDoubleBufferedLayer()
콜백을 트리거합니다.
다음 예에서는 프로세스가 전면 버퍼로 렌더링됩니다. 즉,
사용자가 화면에 그리기를 시작하고 (ACTION_DOWN
) 이동할 때 렌더링됩니다.
포인터를 반환합니다 (ACTION_MOVE
). 프로세스가 이중 버퍼로 렌더링됨
포인터가 화면 표면을 벗어날 때 (ACTION_UP
).
이때
requestUnbufferedDispatch()
드림
입력 시스템이 모션 이벤트를 일괄 처리하지 않고
즉시 사용할 수 있습니다.
Kotlin
when (motionEvent.action) { MotionEvent.ACTION_DOWN -> { // Deliver input events as soon as they arrive. view.requestUnbufferedDispatch(motionEvent) // Pointer is in contact with the screen. glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE) } MotionEvent.ACTION_MOVE -> { // Pointer is moving. glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE) } MotionEvent.ACTION_UP -> { // Pointer is not in contact in the screen. glFrontBufferRenderer.commit() } MotionEvent.CANCEL -> { // Cancel front buffer; remove last motion set from the screen. glFrontBufferRenderer.cancel() } }
Java
switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: { // Deliver input events as soon as they arrive. surfaceView.requestUnbufferedDispatch(motionEvent); // Pointer is in contact with the screen. glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE); } break; case MotionEvent.ACTION_MOVE: { // Pointer is moving. glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE); } break; case MotionEvent.ACTION_UP: { // Pointer is not in contact in the screen. glFrontBufferRenderer.commit(); } break; case MotionEvent.ACTION_CANCEL: { // Cancel front buffer; remove last motion set from the screen. glFrontBufferRenderer.cancel(); } break; }
렌더링 권장사항 및 금지사항
화면의 작은 부분, 필기, 그리기, 스케치
전체 화면 업데이트, 화면 이동, 확대/축소. 테어링이 발생할 수 있습니다.
테어링
테어링은 화면 버퍼가 실행되는 동안 화면을 새로고침할 때 발생합니다. 동시에 수정됩니다. 화면의 일부에는 새 데이터가 표시되고 다른 일부에는 새 데이터가 표시됩니다. 이전 데이터가 표시됩니다.
모션 예측
Jetpack 모션 예측 라이브러리를 사용하면 사용자의 스트로크 경로를 추정하여 체감 지연 시간을 렌더러를 가리키게 합니다.
모션 예측 라이브러리는 실제 사용자 입력을 MotionEvent
객체로 가져옵니다.
객체에는 x 및 y 좌표, 압력 및 시간에 대한 정보가 포함되어 있습니다.
모션 예측기에서 이를 활용하여 미래의 MotionEvent
을(를) 예측합니다.
객체입니다.
예측된 MotionEvent
객체는 추정치일 뿐입니다. 예측된 이벤트로 인해
인지된 지연 시간이지만 예측된 데이터는 실제 MotionEvent
로 대체해야 함
데이터를 전송합니다.
모션 예측 라이브러리는 Android 4.4 (API 수준 19)부터 사용할 수 있으며 이상 및 Android 9 (API 수준 28) 이상을 실행하는 ChromeOS 기기에서 지원됩니다.
종속 항목
모션 예측 라이브러리는 예측 구현을 제공합니다. 이
라이브러리는 앱의 모듈 build.gradle
파일에 종속 항목으로 추가됩니다.
dependencies {
implementation "androidx.input:input-motionprediction:1.0.0-beta01"
}
구현
모션 예측 라이브러리에는
MotionEventPredictor
드림
인터페이스에 포함되어 있으며, 이 클래스는 다음 메서드를 정의합니다.
MotionEventPredictor
의 인스턴스를 선언합니다.
Kotlin
var motionEventPredictor = MotionEventPredictor.newInstance(view)
Java
MotionEventPredictor motionEventPredictor = MotionEventPredictor.newInstance(surfaceView);
예측기에 데이터 제공
Kotlin
motionEventPredictor.record(motionEvent)
Java
motionEventPredictor.record(motionEvent);
예측
Kotlin
when (motionEvent.action) { MotionEvent.ACTION_MOVE -> { val predictedMotionEvent = motionEventPredictor?.predict() if(predictedMotionEvent != null) { // use predicted MotionEvent to inject a new artificial point } } }
자바
switch (motionEvent.getAction()) { case MotionEvent.ACTION_MOVE: { MotionEvent predictedMotionEvent = motionEventPredictor.predict(); if(predictedMotionEvent != null) { // use predicted MotionEvent to inject a new artificial point } } break; }
모션 예측의 권장사항 및 금지사항
새로운 예측 포인트가 추가되면 예측 포인트를 삭제합니다.
최종 렌더링에는 예측 포인트를 사용하지 않습니다.
메모 작성 앱
ChromeOS를 사용하면 앱에서 일부 메모 작성 작업을 선언할 수 있습니다.
ChromeOS에서 앱을 메모 작성 앱으로 등록하려면 입력 호환성을 참고하세요.
Android에서 앱을 메모 작성 앱으로 등록하려면 메모 만들기를 참조하세요. 앱을 엽니다.
Android 14 (API 수준 34)에서는
ACTION_CREATE_NOTE
드림
인텐트를 사용하여 앱이 도어락에서 메모 작성 활동을 시작할 수 있게 해줍니다.
화면
ML Kit를 통한 디지털 잉크 인식
ML Kit 디지털 잉크로 인식, 앱이 수백 개의 디지털 표면에서 필기 텍스트를 인식할 수 있습니다. 있습니다. 스케치를 분류할 수도 있습니다.
ML Kit는
Ink.Stroke.Builder
드림
머신러닝 모델에서 처리할 수 있는 Ink
객체를 만드는 클래스
필기 입력을 텍스트로 변환할 수 있습니다.
모델은 필기 인식 외에도 동작 삭제할 수 있습니다.
디지털 잉크 인식 를 참조하세요.