Ink API가 이제 베타로 제공되며 앱에 통합할 수 있습니다. 이 중요한 단계는 개발자의 소중한 의견 덕분에 가능했으며, 이를 통해 API의 성능, 안정성, 시각적 품질이 지속적으로 개선되었습니다.
Google Docs, Pixel Studio, Google 포토, Chrome PDF, YouTube 효과 메이커와 같은 Google 앱과 서클 투 서치와 같은 Android의 고유 기능은 모두 최신 API를 사용합니다.
이 중요한 시점을 기념하기 위해 모든 크기의 Android 기기, 특히 태블릿과 폴더블 휴대전화에 최적화된 포괄적인 메모 작성 앱 샘플인 Cahier를 출시하게 되어 기쁩니다.
Cahier란 무엇인가요?
Cahier(프랑스어로 '노트북')는 사용자가 텍스트, 그림, 이미지를 결합하여 생각을 포착하고 정리할 수 있는 애플리케이션을 빌드하는 방법을 보여주기 위해 설계된 샘플 앱입니다.
이 샘플은 대형 화면에서 사용자 생산성과 창의성을 향상하는 데 유용한 참고 자료가 될 수 있습니다. 이 샘플에서는 이러한 환경을 빌드하기 위한 권장사항을 보여주어 개발자가 관련 강력한 API와 기법을 더 잘 이해하고 채택할 수 있도록 지원합니다. 이 게시물에서는 Cahier의 핵심 기능, 주요 API, 샘플을 자체 앱의 훌륭한 참조로 만들어 주는 아키텍처 결정을 살펴봅니다.
샘플에서 시연되는 주요 기능은 다음과 같습니다.
- 다양한 메모 작성: 텍스트, 자유 형식 그림, 이미지 첨부파일 등 단일 메모 내에서 여러 형식을 지원하는 유연한 콘텐츠 생성 시스템을 구현하는 방법을 보여줍니다.
- 창의적인 잉크 도구: 잉크 API를 사용하여 고성능의 짧은 지연 시간 그리기 환경을 구현합니다. 이 샘플은 다양한 브러시, 색상 선택기, 실행취소/재실행 기능, 지우개 도구를 통합하는 실제 사례를 제공합니다.
- 드래그 앤 드롭을 사용한 유연한 콘텐츠 통합: 드래그 앤 드롭을 사용하여 수신 및 발신 콘텐츠를 모두 처리하는 방법을 보여줍니다. 여기에는 다른 앱에서 드롭된 이미지를 수락하고 사용자가 원활한 공유를 위해 앱에서 콘텐츠를 드래그할 수 있도록 지원하는 것이 포함됩니다.
- 메모 정리: 빠른 액세스를 위해 메모를 즐겨찾기로 표시합니다. 뷰를 필터링하여 정리하세요.
- 오프라인 우선 아키텍처: Room을 사용하여 오프라인 우선 아키텍처로 빌드되어 모든 데이터가 로컬에 저장되고 인터넷 연결 없이도 앱이 완전히 작동합니다.
- 강력한 멀티 윈도우 및 멀티 인스턴스 지원: 멀티 인스턴스를 지원하여 앱을 여러 창에서 실행할 수 있도록 하는 방법을 보여줍니다. 사용자는 여러 메모를 나란히 작업하여 대형 화면에서 생산성과 창의성을 향상할 수 있습니다.
- 모든 화면에 적합한 적응형 UI: 사용자 인터페이스는 ListDetailPaneScaffold 및 NavigationSuiteScaffold를 사용하여 다양한 화면 크기와 방향에 원활하게 적응하여 스마트폰, 태블릿, 폴더블에서 최적화된 사용자 환경을 제공합니다.
- 심층 시스템 통합: 시스템 전체 메모 인텐트에 응답하여 Android 14 이상에서 앱을 기본 메모 작성 앱으로 만드는 방법을 안내하여 다양한 시스템 진입점에서 콘텐츠를 빠르게 캡처할 수 있도록 지원합니다.
대형 화면에서 생산성과 창의성을 발휘할 수 있도록 설계
초기 출시에서는 생산성 및 창의성 사용 사례 모두에서 Cahier를 핵심 학습 리소스로 만드는 몇 가지 핵심 기능에 중점을 두고 발표할 예정입니다.
적응성의 기반
Cahier는 처음부터 적응형으로 빌드됩니다. 이 샘플에서는 material3-adaptive 라이브러리, 특히 ListDetailPaneScaffold 및 NavigationSuiteScaffold를 사용하여 다양한 화면 크기와 방향에 맞게 앱 레이아웃을 원활하게 조정합니다. 이는 최신 Android 앱의 중요한 요소이며 Cahier는 이를 효과적으로 구현하는 방법을 명확하게 보여줍니다.
Material 3 적응형 라이브러리로 빌드된 Cahier 적응형 UI
주요 API 및 통합 소개
이 샘플은 다음을 비롯하여 자체 애플리케이션에서 활용할 수 있는 강력한 생산성 API를 보여주는 데 중점을 둡니다.
주요 API 자세히 살펴보기
Cahier가 통합하여 최고의 메모 작성 환경을 제공하는 두 가지 핵심 API를 자세히 살펴보겠습니다.
Ink API를 사용한 자연스러운 잉크 환경 만들기
스타일러스 입력은 대형 화면 기기를 디지털 노트북과 스케치북으로 변환합니다. 유연하고 자연스러운 잉크 입력 환경을 빌드할 수 있도록 Ink API를 샘플의 핵심으로 만들었습니다. 잉크 API를 사용하면 동급 최고의 짧은 지연 시간으로 아름다운 잉크 획을 쉽게 생성, 렌더링, 조작할 수 있습니다.
Ink API는 모듈식 아키텍처를 제공하므로 앱의 특정 스택과 요구사항에 맞게 맞춤설정할 수 있습니다. API 모듈에는 다음이 포함됩니다.
- 모듈 작성 (Compose - 뷰): 기기에서 제공할 수 있는 가장 낮은 지연 시간으로 부드러운 획을 만들기 위해 실시간 잉크 입력 처리
- DrawingSurface에서 Cahier는 새로 도입된 InProgressStrokes 컴포저블을 사용하여 실시간 스타일러스 또는 터치 입력을 처리합니다. 이 모듈은 포인터 이벤트를 캡처하고 가능한 최저 지연 시간으로 젖은 잉크 스트로크를 렌더링합니다.
- 획 모듈: 잉크 입력과 시각적 표현을 나타냅니다. 사용자가 선 그리기를 완료하면 onStrokesFinished 콜백이 최종/드라이 Stroke 객체를 앱에 제공합니다. 완료된 잉크 스트로크를 나타내는 이 불변 객체는 DrawingCanvasViewModel에서 관리됩니다.
- 렌더링 모듈: 잉크 스트로크를 효율적으로 표시하여 Jetpack Compose 또는 Android 뷰와 결합할 수 있습니다.
- 기존 스트로크와 새로 건조된 스트로크를 모두 표시하기 위해 Cahier는 DrawingSurface의 CanvasStrokeRenderer를 활성 드로잉에 사용하고 DrawingDetailPanePreview를 메모의 정적 미리보기를 표시하는 데 사용합니다. 이 모듈은 스트로크 객체를 캔버스에 효율적으로 그립니다.
- 브러시 모듈 (Compose - views): 획의 시각적 스타일을 선언적으로 정의하는 방법을 제공합니다. 최근 업데이트 (alpha03 출시 이후)에는 올가미 선택과 같은 기능에 특히 유용한 새로운 점선 브러시가 포함되어 있습니다. DrawingCanvasViewModel은 currentBrush의 상태를 보유합니다. DrawingCanvas의 도구 상자를 사용하면 사용자가 다양한 브러시 모음 (예: StockBrushes.pressurePen() 또는 StockBrushes.highlighter())을 선택하고 색상을 변경할 수 있습니다. ViewModel은 Brush 객체를 업데이트하고, 이 객체는 InProgressStrokes 컴포저블에서 새 스트로크에 사용됩니다.
- 기하학 모듈 (Compose - views): 지우기 및 선택과 같은 기능을 위해 획 조작 및 분석을 지원합니다.
- 도구 상자의 지우개 도구와 DrawingCanvasViewModel의 기능은 geometry 모듈을 사용합니다. 지우개가 활성화되면 사용자의 동작 경로 주위에 MutableParallelogram이 생성됩니다. 그런 다음 지우개는 기존 획의 모양과 경계 상자 간의 교차점을 확인하여 지울 획을 결정하므로 지우개가 직관적이고 정확하게 느껴집니다.
- 스토리지 모듈: 잉크 데이터의 효율적인 직렬화 및 역직렬화 기능을 제공하여 디스크 및 네트워크 크기를 크게 절약합니다. 그림을 저장하기 위해 Cahier는 Room 데이터베이스에 Stroke 객체를 유지합니다. 변환기에서 샘플은 스토리지 모듈의 encode 함수를 사용하여 StrokeInputBatch (원시 포인트 데이터)를 ByteArray로 직렬화합니다. 바이트 배열은 브러시 속성과 함께 JSON 문자열로 저장됩니다. decode 함수는 메모리가 로드될 때 획을 재구성하는 데 사용됩니다.
이러한 핵심 모듈 외에도 최근 업데이트를 통해 Ink API의 기능이 확장되었습니다.
- 맞춤
BrushFamily객체를 위한 새로운 실험적 API를 통해 개발자는 창의적이고 고유한 브러시 유형을 만들 수 있으며, 연필 및 레이저 포인터 브러시와 같은 도구를 만들 수 있습니다.
Cahier는 아래에 소개된 독특한 음악 브러시를 비롯한 맞춤 브러시를 활용하여 고급 크리에이티브 가능성을 보여줍니다.
잉크 API의 맞춤 브러시로 만든 무지개 레이저
Ink API의 맞춤 브러시로 만든 음악 브러시
- 네이티브 Jetpack Compose 상호 운용성 모듈은 Compose UI 내에서 직접 잉크 기능을 통합하여 더욱 관용적이고 효율적인 개발 환경을 제공합니다.
Ink API는 맞춤 구현에 비해 생산성 및 창의성 앱에 이상적인 선택이 되도록 하는 여러 이점을 제공합니다.
- 사용 편의성: Ink API는 그래픽과 기하학의 복잡성을 추상화하여 Cahier의 핵심 기능에 집중할 수 있도록 지원합니다.
- 성능: 기본 제공되는 짧은 지연 시간 지원과 최적화된 렌더링으로 부드럽고 반응성이 뛰어난 잉크 환경을 제공합니다.
- 유연성: 모듈식 설계를 통해 필요한 구성요소를 선택할 수 있으므로 Ink API를 Cahier의 아키텍처에 원활하게 통합할 수 있습니다.
잉크 API는 이미 Docs의 마크업, 서클 투 서치, Orion Notes, PDF 스캐너와 같은 파트너 앱을 비롯한 다양한 Google 앱에 채택되었습니다.
'서클 투 서치 (CtS)에 Ink API를 우선적으로 사용했습니다. 광범위한 문서를 활용하여 Ink API를 쉽게 통합할 수 있었고, 덕분에 단 1주일 만에 첫 번째 작동 프로토타입을 만들 수 있었습니다. Ink의 맞춤 브러시 텍스처와 애니메이션 지원을 통해 스트로크 디자인을 빠르게 반복할 수 있었습니다.' - 조던 코모다, 소프트웨어 엔지니어 - Google
메모 역할로 기본 메모 앱이 되기
메모는 대형 화면 기기에서 사용자 생산성을 향상시키는 핵심 기능입니다. 메모 역할 기능을 사용하면 사용자가 잠금 화면에서 또는 다른 앱이 실행되는 동안 호환되는 앱에 액세스할 수 있습니다. 이 기능은 시스템 전체 기본 메모 앱을 식별하고 설정하며 콘텐츠 캡처를 위해 실행될 수 있는 권한을 부여합니다.
Cahier의 구현
메모 역할을 구현하려면 몇 가지 주요 단계를 거쳐야 하며, 이 모든 단계는 샘플에 나와 있습니다.
- 매니페스트 선언: 먼저 앱이 메모 작성 인텐트를 처리할 수 있는 기능을 선언해야 합니다. AndroidManifest.xml에서 Cahier는 android.intent.action.CREATE_NOTE 작업을 위한
<intent-filter>를 포함합니다. 이는 앱이 메모 역할의 잠재적 후보임을 시스템에 알립니다. - 역할 상태 확인: SettingsViewModel은 Android의 RoleManager를 사용하여 현재 상태를 확인합니다. SettingsViewModel은 기기에서 메모 역할이 사용 가능한지 (isRoleAvailable)와 Cahier가 현재 해당 역할을 보유하고 있는지 (isRoleHeld) 확인합니다. 이 상태는 Kotlin 흐름을 사용하여 UI에 노출됩니다.
- 역할 요청: Settings.kt 파일에서 역할을 사용할 수 있지만 보유하지 않은 경우 사용자에게 Button이 표시됩니다. 클릭하면 버튼이 ViewModel에서
requestNotesRole함수를 호출합니다. 이 함수는 사용자가 Cahier를 선택할 수 있는 기본 앱 설정 화면을 여는 인텐트를 만듭니다. 이 프로세스는 인텐트 실행과 결과 수신을 처리하는 rememberLauncherForActivityResult API를 사용하여 관리됩니다. - UI 업데이트: 사용자가 설정 화면에서 돌아온 후 ActivityResultLauncher 콜백이 ViewModel의 함수를 트리거하여 역할 상태를 업데이트합니다. 이렇게 하면 앱이 이제 기본값인지 여부가 UI에 정확하게 반영됩니다.
메모 앱 만들기 가이드에서 앱에 메모 역할을 통합하는 방법을 알아보세요.
Lenovo 태블릿에서 기본 메모 작성 앱으로 플로팅 창에서 Cahier가 실행됨
중요한 진전: Lenovo에서 메모 역할 사용 설정
대형 화면 Android 생산성을 위한 중요한 진전이 있습니다. Lenovo가 Android 15 이상을 실행하는 태블릿에서 메모 역할 지원을 사용 설정했습니다. 이번 업데이트를 통해 이제 호환되는 Lenovo 기기를 사용하는 사용자가 메모 앱을 기본값으로 설정하여 잠금 화면에서 원활하게 액세스하고 시스템 수준 콘텐츠 캡처 기능을 잠금 해제할 수 있도록 메모 앱을 업데이트할 수 있습니다.
선도적인 OEM의 이러한 노력은 Android에서 진정으로 통합되고 생산적인 사용자 환경을 제공하는 데 메모 역할이 점점 더 중요해지고 있음을 보여줍니다.
멀티 인스턴스, 멀티 윈도우, 데스크톱 창 모드
대형 화면에서의 생산성은 정보와 워크플로를 효율적으로 관리하는 데 달려 있습니다. 이러한 이유로 Cahier는 Android의 고급 창 기능을 완전히 수용하도록 설계되어 사용자 요구에 맞게 조정되는 유연한 작업 공간을 제공합니다. 앱은 다음을 지원합니다.
- 멀티 윈도우: 화면 분할 모드 또는 자유 형식 모드에서 다른 앱과 함께 실행하는 기본 기능입니다. 이는 Cahier에서 메모를 작성하는 동안 웹페이지를 참조하는 등의 작업에 필수적입니다.
- 멀티 인스턴스: 진정한 멀티태스킹이 빛을 발하는 곳입니다. Cahier를 사용하면 사용자가 앱의 독립된 창을 여러 개 동시에 열 수 있습니다. 두 개의 다른 메모를 나란히 비교하거나 한 창에서 그림을 작업하면서 다른 창에서 텍스트 메모를 참조하는 상황을 생각해 보세요. Cahier는 각각 자체 상태를 갖는 이러한 별도의 인스턴스를 관리하여 앱을 강력한 다면적 도구로 전환하는 방법을 보여줍니다.
- 데스크톱 창 모드: 외부 디스플레이에 연결하면 Android 데스크톱 모드가 태블릿이나 폴더블을 워크스테이션으로 변환합니다. Cahier는 적응형 UI로 빌드되고 다중 인스턴스를 지원하므로 이 환경에서 앱이 멋지게 작동합니다. 사용자는 기존 데스크톱처럼 여러 Cahier 창을 열고, 크기를 조절하고, 배치할 수 있으므로 이전에는 휴대기기에서 불가능했던 복잡한 워크플로를 사용할 수 있습니다.
Pixel Tablet에서 데스크톱 창 모드로 실행되는 Cahier
Cahier에서 이러한 기능을 구현한 방법은 다음과 같습니다.
다중 인스턴스를 사용 설정하려면 먼저 AndroidManifest에서 MainActivity의 선언에 PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI 속성을 추가하여 앱이 여러 번 실행될 수 있음을 시스템에 알려야 합니다.
<activity android:name="com.example.cahier.MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.MyApplication" android:showWhenLocked="true" android:turnScreenOn="true" android:resizeableActivity="true" android:launchMode="singleInstancePerTask"> <property android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI" android:value="true"/> ... </activity>
다음으로 앱의 새 인스턴스를 실행하는 로직을 구현했습니다. CahierHomeScreen.kt에서 사용자가 새 창에서 메모를 열도록 선택하면 새 활동 실행 방법을 시스템에 알려주는 특정 플래그가 있는 새 인텐트를 만듭니다. FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_MULTIPLE_TASK, FLAG_ACTIVITY_LAUNCH_ADJACENT를 함께 사용하면 기존 창과 함께 새 창에 메모가 열립니다.
fun openNewWindow(activity: Activity?, note: Note) {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra(AppArgs.NOTE_TYPE_KEY, note.type)
intent.putExtra(AppArgs.NOTE_ID_KEY, note.id)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
activity?.startActivity(intent)
}멀티 윈도우 모드를 지원하려면 매니페스트의 <activity> 또는 <application> 요소를 설정하여 앱이 크기 조절을 지원한다는 신호를 시스템에 보내야 했습니다.
<activity android:name="com.example.cahier.MainActivity" android:resizeableActivity="true" ...> </activity>
Material 3 적응형 라이브러리로 빌드된 UI 자체는 Android의 화면 분할 모드와 같은 멀티 윈도우 시나리오에서 원활하게 적응할 수 있습니다.
사용자 환경을 개선하기 위해 드래그 앤 드롭 지원이 추가되었습니다. Cahier에서 이를 구현한 방법은 아래를 참고하세요.
드래그 앤 드롭
진정으로 생산적이거나 창의적인 앱은 격리된 상태로 작동하지 않습니다. 기기 생태계의 나머지 부분과 원활하게 상호작용합니다. 드래그 앤 드롭은 특히 사용자가 여러 앱 창에서 작업하는 경우가 많은 대형 화면에서 이러한 상호작용의 핵심입니다. Cahier는 콘텐츠 추가와 공유를 위한 직관적인 드래그 앤 드롭 기능을 구현하여 이를 완전히 수용합니다.
- 간편한 가져오기: 사용자는 웹브라우저, 사진 갤러리, 파일 관리자와 같은 다른 애플리케이션에서 이미지를 드래그하여 메모 캔버스에 직접 드롭할 수 있습니다. 이를 위해 Cahier는 dragAndDropTarget 수정자를 사용하여 드롭 영역을 정의하고, 호환되는 콘텐츠 (예:
image/*)를 확인하고, 수신되는 URI를 처리합니다. - 간단한 공유: Cahier 내부의 콘텐츠는 다른 앱의 콘텐츠와 마찬가지로 쉽게 공유할 수 있습니다. 사용자는 텍스트 메모 내에서 이미지를 길게 누르거나 그림 메모 및 이미지 컴포지션의 전체 캔버스를 길게 눌러 다른 애플리케이션으로 드래그할 수 있습니다.
기술 심층 분석: 그리기 캔버스에서 드래그
그리기 캔버스에서 드래그 동작을 구현하는 데는 고유한 문제가 있습니다. DrawingSurface에서 라이브 드로잉 입력 (Ink API의 InProgressStrokes)을 처리하는 컴포저블과 드래그를 시작하기 위해 길게 누르기 동작을 감지하는 Box는 동위 컴포저블입니다.
기본적으로 Jetpack Compose 포인터 입력 시스템은 터치 위치와 겹치는 선언 순서의 첫 번째 형제 컴포저블 하나만 이벤트를 수신하도록 설계되어 있습니다. Cahier의 경우 InProgressStrokes 컴포저블이 그리기 위해 사용되지 않은 모든 입력을 사용한 후 해당 입력을 소비하기 전에 드래그 앤 드롭 입력 처리 로직이 실행되어 입력을 소비할 수 있도록 해야 합니다. 올바른 순서로 정렬하지 않으면 Box에서 드래그를 시작하기 위한 길게 누르기 동작을 감지하지 못하거나 InProgressStrokes에서 그리기 위한 입력을 수신하지 못합니다.
이 문제를 해결하기 위해 맞춤 pointerInputWithSiblingFallthrough 수정자를 만들고 컴포저블 코드에서 해당 수정자를 사용하여 Box를 InProgressStrokes 앞에 배치했습니다. 이 유틸리티는 표준 pointerInput 시스템을 래핑하지만 한 가지 중요한 변경사항이 있습니다. sharePointerInputWithSiblings() 함수를 재정의하여 true를 반환합니다. 이렇게 하면 포인터 이벤트가 사용된 후에도 형제 컴포저블로 전달되도록 Compose 프레임워크에 지시합니다.
internal fun Modifier.pointerInputWithSiblingFallthrough(
pointerInputEventHandler: PointerInputEventHandler
) = this then PointerInputSiblingFallthroughElement(pointerInputEventHandler)
private class PointerInputSiblingFallthroughModifierNode(
pointerInputEventHandler: PointerInputEventHandler
) : PointerInputModifierNode, DelegatingNode() {
var pointerInputEventHandler: PointerInputEventHandler
get() = delegateNode.pointerInputEventHandler
set(value) {
delegateNode.pointerInputEventHandler = value
}
val delegateNode = delegate(
SuspendingPointerInputModifierNode(pointerInputEventHandler)
)
override fun onPointerEvent(
pointerEvent: PointerEvent,
pass: PointerEventPass,
bounds: IntSize
) {
delegateNode.onPointerEvent(pointerEvent, pass, bounds)
}
override fun onCancelPointerInput() {
delegateNode.onCancelPointerInput()
}
override fun sharePointerInputWithSiblings() = true
}
private data class PointerInputSiblingFallthroughElement(
val pointerInputEventHandler: PointerInputEventHandler
) : ModifierNodeElement<PointerInputSiblingFallthroughModifierNode>() {
override fun create() = PointerInputSiblingFallthroughModifierNode(pointerInputEventHandler)
override fun update(node: PointerInputSiblingFallthroughModifierNode) {
node.pointerInputEventHandler = pointerInputEventHandler
}
override fun InspectorInfo.inspectableProperties() {
name = "pointerInputWithSiblingFallthrough"
properties["pointerInputEventHandler"] = pointerInputEventHandler
}
}DrawingSurface에서 사용되는 방식은 다음과 같습니다.
Box(
modifier = Modifier
.fillMaxSize()
// Our custom modifier enables this gesture to coexist with the drawing input.
.pointerInputWithSiblingFallthrough {
detectDragGesturesAfterLongPress(
onDragStart = { onStartDrag() },
onDrag = { _, _ -> /* consume drag events */ },
onDragEnd = { /* No action needed */ }
)
}
)
// The Ink API's composable for live drawing sits here as a sibling.
InProgressStrokes(...)이렇게 하면 시스템에서 그리기 스트로크와 길게 누르기 드래그 동작을 동시에 올바르게 감지합니다. 드래그가 시작되면 FileProvider를 사용하여 공유 가능한 content:// URI를 만들고 view.startDragAndDrop()을 사용하여 URI를 시스템의 드래그 앤 드롭 프레임워크에 전달합니다. 이 솔루션은 강력하고 직관적인 사용자 환경을 보장하며, 계층화된 UI에서 복잡한 동작 충돌을 극복하는 방법을 보여줍니다.
최신 아키텍처로 빌드
Cahier는 특정 API 외에도 고품질의 적응형 애플리케이션을 빌드하기 위한 중요한 아키텍처 패턴을 보여줍니다.
프레젠테이션 계층: Jetpack Compose 및 적응성
프레젠테이션 계층은 Jetpack Compose로 완전히 빌드됩니다. 앞서 언급한 것처럼 Cahier는 UI 적응성을 위해 material3-adaptive 라이브러리를 채택합니다. 상태 관리는 엄격한 단방향 데이터 흐름 (UDF) 패턴을 따르며, ViewModel 인스턴스는 메모 정보와 UI 상태를 보유하는 데이터 컨테이너로 사용됩니다.
데이터 레이어: 저장소 및 Room
데이터 레이어의 경우 Cahier는 NoteRepository 인터페이스를 사용하여 모든 데이터 작업을 추상화합니다. 이 설계 선택을 통해 앱은 로컬 데이터 소스 (Room)와 잠재적인 향후 원격 백엔드 간에 깔끔하게 전환할 수 있습니다. 메모 수정과 같은 작업의 데이터 흐름은 간단합니다.
- Jetpack Compose UI가 ViewModel에서 메서드를 트리거합니다.
- ViewModel은 NoteRepository에서 메모를 가져오고, 로직을 처리하고, 업데이트된 메모를 저장소에 다시 전달합니다.
- NoteRepository는 업데이트를 Room 데이터베이스에 저장합니다.
포괄적인 입력 지원
진정한 생산성 강자가 되려면 앱이 다양한 입력 방식을 완벽하게 처리해야 합니다. Cahier는 대형 화면 입력 가이드라인을 준수하도록 빌드되었으며 다음을 지원합니다.
- 스타일러스: Ink API와의 통합, 손바닥 감지, 메모 역할 등록, 텍스트 필드의 스타일러스 입력, 몰입형 모드
- 키보드: 가장 일반적인 단축키와 조합 (예: Ctrl+클릭, Meta+클릭) 지원 및 키보드 포커스 명확하게 표시
- 마우스 및 트랙패드: 마우스 오른쪽 버튼 클릭 및 마우스 오버 상태 지원
고급 키보드, 마우스, 트랙패드 상호작용 지원은 향후 개선의 핵심입니다.
지금 시작하세요
Cahier가 다음 멋진 앱을 위한 발판이 되기를 바랍니다. 적응형 UI, 잉크 및 메모 역할과 같은 강력한 API, 최신 적응형 아키텍처를 결합하는 방법을 보여주는 포괄적인 오픈소스 리소스로 빌드되었습니다.
시작할 준비가 되셨나요?
- 코드 살펴보기: GitHub 저장소로 이동하여 Cahier 코드베이스를 살펴보고 디자인 원칙이 실제로 적용되는 방식을 확인하세요.
- 직접 빌드: Cahier를 자체 메모 작성, 문서 마크업 또는 창작 애플리케이션의 기반으로 사용합니다.
- 참여: Google은 여러분의 참여를 언제든지 환영합니다. Android 개발자 커뮤니티를 위한 Cahier를 더욱 유용한 리소스로 만들 수 있도록 도와주세요.
공식 개발자 가이드를 확인하고 지금 바로 차세대 생산성 및 창의성 앱을 빌드하세요. 앞으로 여러분이 만들 멋진 결과물을 기대하겠습니다.
계속 읽기
-
방법
과도한 배터리 소모가 Android 사용자의 가장 큰 관심사임을 인식한 Google은 개발자가 더 효율적인 앱을 빌드할 수 있도록 지원하기 위해 상당한 조치를 취해 왔습니다.
Alice Yuan • 8분 읽기
-
방법
온디바이스 모델과 클라우드 모델을 모두 사용하는 AI 지원 기능의 예를 제공하여 사용자에게 즐거운 경험을 선사할 수 있도록 영감을 드리고자 합니다.
Thomas Ezan, Ivy Knight • 전문 길이: 2분
-
방법
성능 레벨링 가이드에는 5가지 레벨이 있습니다. 최소한의 채택 노력 성능 도구를 소개하는 레벨 1부터 맞춤 성능 프레임워크를 유지할 리소스가 있는 앱에 적합한 레벨 5까지 살펴봅니다.
Alice Yuan • 읽는 데 9분 소요
소식 받아 보기
Android 개발 관련 최신 정보를 이메일로 받아 보세요.