본문 바로가기
[Developer]/Android

[Wear OS] 시계 모드에 컴플리케이션 및 제스처 추가

by 해피빈이 2022. 4. 11.

Photo by Samer Khodeir on Unsplash

워치페이스는 WatchFaceService 클래스에서 상속받아 구현하게 된다. 그렇다면, 각종 정보 제공을 위한 컴플리케이션은 이 클래스 내부에 어떻게 구현해야 할까? 아래의 방법으로 간단하게 추가할 수 있다. 다만, 원하는 형태로 제공하기 위해서는 조금은 추가 학습이 필요할 수 있다.(그림 그리는 부분 및 데이터의 출처와 종류 조사가 필요하기 때문)

 

시계 모드에 컴플리케이션 추가하기

워치페이스에 컴플리케이션을 사용하면 데이터 소스의 데이터를 표시할 수 있다. Complications API를 사용하면 워치페이스에서 기본 데이터를 가져오는 데 사용할 데이터 소스를 선택할 수 있다. 이를 통해 워치페이스는 데이터를 가져오기 위한 코드가 없어도 시간 정보 이외의 정보를 표현하는 것이 가능해진다.

Wearable Support Library를 AndroidX로 마이그레이션 할 경우, ComplicationProvider가 ComplicationDataSource로 변경되었다는 것을 참고하자.

ComplicationsSlotsManager 사용하기

컴플리케이션을 워치페이스로 추가하기 위해서는 ComplicationSlotsManager를 추가해야 한다.

ComplicationSlotsManager에는 워치페이스에 얼마나 많은 수의 컴플리케이션을 지원하는지, 화면의 어느곳에 있는지에 대해 정의된다. 컴플리케이션의 위치와 개수에 대해 변경하는 것을 지원하기 위해서는 아래의 예시처럼 ComplicationSlotsManager는 CurrentUserStyleRepository를 사용해야 한다.

아래의 코드는 WatchFaceService class를 상속받아 구현할 때의 내용이다.

override fun createComplicationSlotsManager(
        currentUserStyleRepository: CurrentUserStyleRepository
    ): ComplicationSlotsManager {
        val defaultCanvasComplicationFactory =
            CanvasComplicationFactory { watchState, listener ->
                // ...
            }

        val leftComplicationSlot = ComplicationSlot.createRoundRectComplicationSlotBuilder(
            id = 100,
            canvasComplicationFactory = defaultCanvasComplicationFactory,
            // ...
        )
            .setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
            .build()

        val rightComplicationSlot = ComplicationSlot.createRoundRectComplicationSlotBuilder(
            id = 101,
            canvasComplicationFactory = defaultCanvasComplicationFactory,
            // ...
        )
            .setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
            .build()

        return ComplicationSlotsManager(
            listOf(leftComplicationSlot, rightComplicationSlot),
            currentUserStyleRepository
        )
 }

타입과 필드

일반 타입

다음 표에서는 ComplicationData 객체의 타입과 필드에 대해 설명한다. 워치페이스가 컴플리케이션 타입에 대해 유효하지 않은 필드를 요청하면 해당 필드의 기본값이 반환된다. 예를 들어 워치페이스가 SHORT_TEXT 타입의 LONG_TEXT 필드를 접근하려고 하면, LONG_TEXT 필드의 default 값인 null이 리턴된다.

 
타입
 
 
필수 필드
 
 
선택적 필드
 
 
노트
 
 
SHORT_TEXT
 
Short text
Icon, Burn-in protection icon, Short title
Icon 또는 Short title 중 하나 또는 둘 다 제공되는 경우에는 하나만 표시된다.
 
ICON
 
Icon
Burn-in protection icon
텍스트가 필요하지 않을 때 사용된다. Icon은 단색이어야 하며 워치페이스에 의해 색이 입혀질 수 있다.
 
RANGED_VALUE
 
Value, Min value, Max value
Icon, Burn-in protection icon, Short text, Short title
선택필드는 표시되지 않을 수 있다. 나만의 진행률 표시줄을 그리고 싶다면, ComplicationDrawable class에서 제공하는 진행률 표시줄을 숨기는 isRangedValueProgressHidden()메서드를 이용하면 된다.
 
LONG_TEXT
 
Long text
Long title, Icon, Burn-in protection icon, Small image
제공된다면 Long Text를 보여준다.
 
SMALL_IMAGE
 
Small image
 
작은 이미지는 사진 스타일 또는 아이콘 스타일 중 하나일 수 있다. 사진 스타일은 공간을 채우거나 잘릴 수 있으며, 아이콘 스타일은 잘리지 않고 패딩되는 것을 의미한다. 안전을 위해서 번인 방지 혹은 낮은 비트모드에서는 Burn-in protection small image가 사용될 수 있다. 그렇지 않으면 적합하지 않으므로 이미지를 표시하지 않도록 해야 한다.
 
LARGE_IMAGE
 
Large image
 
이미지가 워치페이스를 가득채울만큼 클 것으로 예상된다. 이미지 가변성으로 인해 번인 보호기능이나 낮은 비트모드에서는 적합하지 않게 표시될 수도 있다. 그러므로 이런 경우 이미지를 표시하지 않도록 해야 한다.

 

빈 데이터용 타입

아래 타입은 빈 데이터용이며, 모든 컴플리케이션 슬롯에 전송될 수 있다. 이러한 타입에는 필드가 없으며, 지원되는 타입에 포함될 필요가 없다. 이러한 타입을 통해 워치페이스는 다음 세 가지 경우를 구별할 수 있다.

  • 소스를 선택하지 않음
  • 사용자가 슬롯에 대해 “empty”를 선택함
  • 소스에서 보낼 데이터가 없음

소스는 업데이트 요청에 대한 응답으로 ‘TYPE_EMPTY’를 보내지 않아야 한다. 소스는 대신 ‘TYPE_NO_DATA’를 보내야 한다. “empty” 데이터에 대한 컴플리케이션 타입 세부 정보는 아래에 설명하고 있다.

  1. TYPE_NOT_CONFIGURED
    컴플리케이션이 활성화 되었지만, 사용자가 소스를 선택하지 않았고, 기본값이 설정되지 않은 경우 시스템에서 전송한다. 소스에서 보낼 수 없다.
  2. TYPE_EMPTY
    컴플리케이션이 활성화 되고, 사용자가 소스 대신 “empty”를 선택하거나, 워치페이스에서 소스를 선택하지 않고 이 컴플리케이션 타입을 기본값으로 선택한 경우 시스템에서 보내게 된다. 소스에서 보낼 수 없다.
  3. TYPE_NO_DATA
    소스에서 실제 데이터를 수신하기 전에 컴플리케이션(소스가 있는 정보)이 컴플리케이션을 클리어 하기 위해 활성화 될 때 시스템에서 보내는 경우이다. 소스에서 보낼 실제 데이터가 없는 경우에는 이것으로 보내야 한다.

 

대화형 시계 모드 만들기

사용자는 다양한 방법으로 워치페이스와 상호작용할 수 있다. 예를 들어, 사용자는 현재 재생중인 노래를 알아보거나 오늘의 일정을 보기 위해 워치페이스를 탭 할수 있다. Wear OS 를 사용하면 해당 제스처에 응답하는 다른 UI 요소가 없는 한 워치페이스에서 시계 모드의 지정된 위치에서 단일 탭 제스처를 받아들일 수 있다.

워치페이스 스타일 구성이 끝나면 다음의 제스처 처리를 통해 대화형 시계 모드로 구현이 가능하다.

탭 이벤트 처리

워치페이스에서는 오직 사용자가 화면에 손가락을 대었다가 떼는 이벤트인 탭 이벤트만 제공된다. 손가락이 터치스크린에 있는 동안 사용자가 다른 타입의 제스처를 수행하는 경우 다른 모든 제스처는 시스템에서 다른 기능을 위해 워치페이스는 취소 이벤트를 수신한다.

탭 제스처를 처리하려면 setTapListener()에 TapListener를 추가한다.

워치페이스는 다음 타입의 터치이벤트를 수신한다.

  • TapType.DOWN: 사용자가 터치스크린에 손가락을 대었을 때
  • TapType.UP: 사용자가 터치스크린에서 손자락을 떼었을 때
  • TapType.CANCEL: 시스템이 사용자가 탭 이외의 다른 제스처를 수행하고 있음을 감지한 경우

워치페이스가 TapType.CANCEL 이벤트를 수신하면 시스템이 이미 제스처를 처리하고 있으므로, 어떤 작업도 반응하도록 하면 안된다.

android.view.ViewConfiguration.getScaledTouchSlop()에서 반환되는 값에 따라 TapType.DOWN 이벤트와 TapType.UP 이벤트가 연속될 경우 탭으로 확인된다.

 

출처 및 참고자료

반응형

댓글